T-SQL确定历史记录表中的状态更改

时间:2011-08-11 22:00:23

标签: tsql sql-server-2008

我有一个应用程序,它将“生产”表中记录的更改记录到“历史”表中。历史表基本上是生产表的字段副本的字段,有一些额外的列,如上次修改日期,最后由用户修改等。

这很有效,因为我们会在记录更改时随时获取记录的快照。但是,它很难确定记录的唯一状态更改。下面是一个例子。

BoxID   StatusID   SubStatusID   ModifiedTime
 1         4            27       2011-08-11 15:31
 1         4            11       2011-08-11 15:28
 1         4            11       2011-08-10 09:07
 1         5            14       2011-08-09 08:53
 1         5            14       2011-08-09 08:19
 1         4            11       2011-08-08 14:15
 1         4            9        2011-07-27 15:52
 1         4            9        2011-07-27 15:49
 1         2            8        2011-07-26 12:00

正如您在上表中看到的那样(数据来自真实系统,其他字段为了简洁和安全而被删除)BoxID 1对生产记录进行了9次更改。其中一些更新导致状态发生变化,而另一些则没有,这意味着其他字段(未显示)已更改。

我需要能够在TSQL中从这些数据中提取唯一的状态更改。鉴于上面的输入表,我正在寻找的输出在下面。

BoxID   StatusID   SubStatusID   ModifiedTime
 1         4            27       2011-08-11 15:31
 1         4            11       2011-08-10 09:07
 1         5            14       2011-08-09 08:19
 1         4            11       2011-08-08 14:15
 1         4            9        2011-07-27 15:49
 1         2            8        2011-07-26 12:00

这不像通过StatusID和SubStatusID进行分组那样容易,然后将min(ModifiedTime)连接回历史表,因为状态也可以倒退(参见StatusID 4,SubStatusID 11设置两次)。

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:5)

这对你有用吗<​​/ p>

;WITH Boxes_CTE AS
    (
    SELECT Boxid, StatusID, SubStatusID, ModifiedTime,
        ROW_NUMBER() OVER (PARTITION BY Boxid ORDER BY ModifiedTime) AS SEQUENCE
    FROM Boxes
    )

SELECT b1.Boxid, b1.StatusID, b1.SubStatusID, b1.ModifiedTime
FROM Boxes_CTE b1
LEFT OUTER JOIN Boxes_CTE b2 ON b1.Boxid = b2.Boxid
            AND b1.Sequence = b2.Sequence + 1
WHERE b1.StatusID <> b2.StatusID
    OR b1.SubStatusID <> b2.SubStatusID
    OR b2.StatusID IS NULL
ORDER BY b1.ModifiedTime DESC
;

答案 1 :(得分:2)

Select BoxID,StatusID,SubStatusID FROM Staty CurrentStaty
INNER JOIN ON 
(
Select BoxID,StatusID,SubStatusID FROM Staty PriorStaty 
) 
Where Staty.ModifiedTime=
                          (Select Max(PriorStaty.ModifiedTime) FROM PriorStaty
                           Where PriortStaty.ModifiedTime<Staty.ModifiedTime)
AND Staty.BoxID=PriorStaty.BoxID
AND NOT (
         Staty.StatusID=PriorStaty.StatusID
         AND 
         Staty.SubStatusID=PriorStaty.StatusID
)