create table #X
(
PK varchar(12) not null,
UpdateDate datetime not null,
Version int not null,
RowData xml not null
);
create table #T
(
PK varchar(12) not null,
UpdateDate datetime not null,
ColumnName nvarchar(128) not null,
Value varchar(max),
Version int not null
);
insert into #X(PK, UpdateDate, Version, RowData)
select bt.PK,
bt.UpdateDate,
0,
(select bt.* for xml path(''), elements xsinil, type)
from dbo.bigtable as bt
union all
select bt.PK,
bt.UpdateDate,
row_number() over(partition by bt.PK order by bt.UpdateDate desc),
(select bt.* for xml path(''), elements xsinil, type)
from dbo.bigtable_archive as bt;
with C as
(
select X.PK,
X.UpdateDate,
X.Version,
T.C.value('local-name(.)', 'nvarchar(128)') as ColumnName,
T.C.value('text()[1]', 'varchar(max)') as Value
from #X as X
cross apply X.RowData.nodes('*') as T(C)
)
insert into #T (PK, UpdateDate, ColumnName, Value, Version)
select C.PK,
C.UpdateDate,
C.ColumnName,
C.Value,
C.Version
from C
where C.ColumnName not in (N'PK', N'UpdateDate');
/*
option (querytraceon 8649);
The above query might need some trick to go parallel.
For the testdata I had on my machine exection time is 16 seconds vs 2 seconds
https://web.archivesqlkiwi.org/web/20180404164406/http://sqlblogblogspot.com/blogs/paul_white/archive/2011/12/23/forcing-a-parallel-query-execution-plan.aspxhtml
http://dataeducation.com/next-level-parallel-plan-forcing-an-alternative-to-8649/
*/
select New.PK,
New.UpdateDate,
New.ColumnName,
Old.Value as OldValue,
New.Value as NewValue
from #T as New
left outer join #T as Old
on Old.PK = New.PK and
Old.ColumnName = New.ColumnName and
Old.Version = New.Version + 1;
Mikael Eriksson
- 22.2k
- 5
- 61
- 104
Extracting XML to temptable before shredding makes it a bit faster. Parallel hash plan might also be better
Mikael Eriksson
- 22.2k
- 5
- 61
- 104