Reputation: 107
I am developing an application and my boss wants to track all changes that have been made to a record throughout its life.
For instance, if I have the following table:
ID Name City Item Version
1 Mike Miami Test box 1
1 Mike Fort Lauderdale Test box 2
1 Mike Sarasota Testing box 3
And I want to see that from version 1 to version 2 the city was changed to Fort Lauderdale, is there a query that will help me do that? I would really like to be able to do this without specifying all the column names individually, because the actual table has 25+ columns and they may change at any time, plus it would be nice if the query could be easily portable to different tables. Ideally my result would look like the following, but I'm willing to accept anything that would help. Thanks in advance!
ColumnName Previous Value New Value
City Miami Fort Lauderdale
Upvotes: 0
Views: 218
Reputation: 1270191
Assuming that the columns are all strings (which is rather necessary for your output format), you can do this by unpivoting the data and using lag()
:
select c.*
from (select t.id,
lag(v.col) over (partition by t.id order by t.version) as prev_val,
v.val
from t cross apply
(values ('Name', name), ('City', city), ('Item', item)
) v(col, val)
) c
where prev_val <> val;
If you have columns that are not strings, then you'll need to convert them to strings in the values
clause.
This also assumes that the values are not NULL
. That can be handled, but does not seem necessary.
Upvotes: 1