I have a vehicle registration table laid out as follows:
CREATE TABLE [registrations]
(
[VIN] int,
[Name] nvarchar(255),
[Action] nvarchar(255),
[Date] DateTime
);
INSERT INTO registrations VALUES
(1, 'John', 'Add', '2017-01-01'),
(1, '', 'Remove', '2017-01-16'),
(1, 'Fred', 'Add', '2017-02-25'),
(1, 'Tom', 'Change', '2017-06-08'),
(2, 'Nancy', 'Add', '2018-01-15'),
(2, 'Jim', 'Change', '2018-02-05'),
(3, 'Clarence', 'Add', '2018-02-10'),
(3, 'Darlene', 'Change', '2018-02-11'),
(4, 'Charlotte', 'Add', '2018-02-11'),
(5, 'Ferris', 'Add', '2018-02-12'),
(5, 'Dante', 'Change', '2018-02-12'),
(5, 'Susan', 'Change', '2018-02-13');
I'm trying to capture only actions Change
, but I want the Name
value before and after the change as different columns in the same row.
So a query on the above would return something like:
VIN OldName NewName Date
1 Fred Tom 2017-02-25
2 Nancy Jim 2018-02-05
3 Clarence Darlene 2018-02-11
5 Dante Susan 2018-02-13
Note: I'm excluding VINs with only 1 transaction, and a Change
can come from more than one status (e.g. Add
).
Other answers (1) show a great way to do this, but by monitoring a single column changing. I have multiple columns changing (Name
is just an example of one), with a flag column (Action
) indicating a change was made on any of the rows.
I can get it into a log-looking usable format using guidance from another answer (2):
WITH T AS
(
SELECT *, COUNT(*) OVER (PARTITION BY VIN) as Cnt
FROM [registrations]
)
SELECT [VIN], [Action], [Name], [Date]
FROM T
WHERE Cnt > 1
order by [VIN], [Date] desc
But in terms of PIVOT
ing, I'm not sure how to factor in the fact that there could be 2 or there could be 10 entries per VIN
. I only would really want the most recent two (the most recent being the Change
).
I'm able to do the extra processing on the above query at application level, but I'd like to know how to do this in SQL.
RDBMS: MS SQL Server 2005
SQLFiddle: http://sqlfiddle.com/#!18/f579f/1