【发布时间】:2011-12-06 04:36:36
【问题描述】:
我需要创建一个进程,该进程将从表中提取更改,其中每一行都是另一个表中一行的快照。现实世界的问题涉及到很多表,很多字段,但是作为一个简单的例子,假设我有以下快照数据:
Sequence DateTaken ID Field1 Field2
-------- ----------- ---- ------ ------
1 '2011-01-01' 1 'Red' 2
2 '2011-01-01' 2 'Blue' 10
3 '2011-02-01' 1 'Green' 2
4 '2011-03-01' 1 'Green' 3
5 '2011-03-01' 2 'Purple' 2
6 '2011-04-01' 1 'Yellow' 2
Sequence 和 DateTaken 字段与快照表本身直接相关。 ID 字段是源表的主键,Field1 和 Field2 是同一(源)表中的其他字段。
我可以通过这样的查询获得部分解决方案:
WITH Snapshots (Sequence, DateTaken, ID, Field1, Field2, _Index)
AS
(
SELECT Sequence, DateTaken, ID, Field1, Field2, ROW_NUMBER() OVER (ORDER BY ID, Sequence) _Index
FROM #Snapshots
)
SELECT
c.DateTaken, c.ID
, c.Field1 Field1_Current, p.Field1 Field1_Previous, CASE WHEN c.Field1 = p.Field1 THEN 0 ELSE 1 END Field1_Changed
, c.Field2 Field2_Current, p.Field2 Field2_Previous, CASE WHEN c.Field2 = p.Field2 THEN 0 ELSE 1 END Field2_Changed
FROM Snapshots c
JOIN Snapshots p ON p.ID = c.ID AND (p._Index + 1) = c._Index
ORDER BY c.Sequence DESC
上面的查询将识别从一个快照到下一个快照的变化,但它仍然不是我需要的形式。输出中的每一行都可能包含多个更改。在一天结束时,我需要每次更改一行来标识更改的字段及其先前/当前值。实际未更改的字段将需要从最终输出中排除。所以如果上面的查询输出是这样的:
DateTaken ID Field1_Current Field1_Previous Field1_Changed Field2_Current Field2_Previous Field2_Changed
---------- -- -------------- --------------- -------------- -------------- --------------- --------------
2011-04-01 1 Yellow Green 1 2 3 1
2011-02-01 1 Green Red 1 2 2 0
我需要把它变成这样的东西:
DateTaken ID Field Previous Current
---------- -- ------- -------- ---------
2011-04-01 1 Field1 Green Yellow
2011-04-01 1 Field2 3 2
2011-02-01 1 Field1 Red Green
我认为我可以通过 UNPIVOT 实现这一目标,但我无法做到这一点。我认为任何涉及游标或类似的解决方案都是绝对的最后手段。
非常感谢您的建议。
【问题讨论】:
-
我遇到了同样的问题。请参阅stackoverflow.com/questions/6348405/… 注意您需要强制转换,因为您将遇到数据类型问题
标签: sql sql-server sql-server-2005