Puoi ricostruire i record. La query sarà un po 'ingombrante. La logica deve fare quanto segue per un determinato campo, il valore è dato dalle seguenti regole:
- Il nuovo valore del record con la versione più piccola successiva di @VersionNumber
- Il vecchio valore del record con la versione successiva successiva di @VersionNumber
- Il valore corrente
Ecco un esempio (con meno campi):
select t1.objId, t1.userId,
max(case when tv.FieldName = 'Data1' and VersionNumber < @VersionNumber
then tv.NewValue
when tv.FieldName = 'Data1' and VersionNumber > @VersionNumber
then tv.OldValue
when tv.FieldName = 'Data1' and VersionNumber is null
then t.Data1
end) as Data1,
max(case when tv.FieldName = 'Data2' and VersionNumber < @VersionNumber
then tv.NewValue
when tv.FieldName = 'Data2' and VersionNumber > @VersionNumber
then tv.OldValue
when tv.FieldName = 'Data2' and VersionNumber is null
then t.Data2
end) as Data2,
. . .
from table1 t1 left outer join
(select tv.*,
row_number() over (partition by objId, userId, fieldname
order by abs(VersionNumber - @VersionNumber)
) as seqnum
from table_var tv
) tv
on tv.objId = t.objId and tv.userId = t.userId and seqnum = 1
group by t1.objId, t1.userId;
Una sfida con questa logica è essere sicura che il valore corrente non si mescoli accidentalmente nei valori precedenti. Il left outer join
insieme a seqnum = 1
gestisce questo. Il valore corrente viene utilizzato solo quando non c'è corrispondenza con un valore precedente o successivo.