我有一个遗留数据库,其中一些表通过以下方式进行版本化:每个字段单独 - 只有那些改变了;
Table1
ObjID userID Data1 Data2 Data3
----- ------ ----- ---- ----
11 1 A null 123
222 1 H 111 999
33 2 C 222 333
Table1_ver
ObjID userID FieldName OldValue VersionNumber
----- ------ ----- ---- ----
222 1 Data1 F 5
222 1 Data1 A 8
222 1 Data2 888 10
33 8 Data1 G 10
当前版本存储在其他一些表格中 - 现在说是11;当更改发生时,旧数据值与“旧”版本号(旧值所属的版本号)一起记录,然后版本号增加
这些表有很多字段(> 20)和大量记录,所以我想最初的想法是使用较少的存储空间进行版本控制。现在我需要添加功能来在给定的时间点(按版本)重建数据。我怎样才能以优雅高效的方式实现它 - 最好不使用动态SQL,而是采用一些基于集合的方法。可以在SQL中以良好的性能完成吗?谢谢!
答案 0 :(得分:3)
您可以重建记录。查询会有点麻烦。逻辑是执行以下操作对于给定字段,该值由以下规则给出:
以下是一个示例(字段较少):
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;
使用此逻辑的一个挑战是确保当前值不会意外混合以前的值。 left outer join
与seqnum = 1
处理此问题。仅当与前一个值或后一个值不匹配时,才会使用当前值。