【问题标题】:SQL Server Return Rows Where Field ChangedSQL Server 返回字段更改的行
【发布时间】:2015-12-29 14:54:45
【问题描述】:

我有一个包含 3 个值的表。

ID     AuditDateTime       UpdateType
12     12-15-2015 18:09    1
45     12-04-2015 17:41    0
75     12-21-2015 04:26    0
12     12-17-2015 07:43    0
35     12-01-2015 05:36    1
45     12-15-2015 04:35    0

我正在尝试仅返回基于 ID 的 UpdateType 已从 AuditDateTime 更改的记录。所以在本例中,ID 12 从 12-15 条目变为 12-17 条目。我希望该记录返回。将有多个 ID 12 实例,我需要返回 ID 的 UpdateType 与其上一个条目相比发生变化的所有记录。我尝试添加一个row_number,但它没有按顺序插入,因为表中的记录不是按顺序排列的。我已经做了很多搜索但没有运气。任何帮助将不胜感激。

【问题讨论】:

    标签: sql sql-server record


    【解决方案1】:

    通过使用 CTE,可以根据 AuditDateTime 的顺序找到以前的记录

    WITH CTEData AS 
    (SELECT ROW_NUMBER() OVER (PARTITION BY ID ORDER BY AuditDateTime) [ROWNUM], *
    FROM @tmpTable)
    SELECT A.ID, A.AuditDateTime, A.UpdateType 
    FROM CTEData A INNER JOIN CTEData B 
            ON  (A.ROWNUM - 1) = B.ROWNUM AND 
                A.ID = B.ID 
    WHERE A.UpdateType <> B.UpdateType 
    

    回到 CTE 的内部连接将在一次查询中提供当前记录(表别名 A)和上一行(表别名 B)。

    【讨论】:

    • 当存在日期为 12-16-2015 的行并为 ID 12 更新类型 0 时,这仍将返回 ID 12。
    • 它应该返回 ID 12,因为 2015 年 12 月 15 日的记录的更新类型为 1。返回的数据将针对这条新记录。
    • 尝试插入日期为:12-16-2015,更新类型:0 和 ID 12 的行。在这种情况下,它仍然会返回 ID 12,而不会被要求这样做。 (我需要返回 ID 的 UpdateType 与之前的条目相比发生变化的所有记录
    • 更新类型已从上一个条目更改,ID 12 的第一个和第二个条目已更改。第一个条目是 1,第二个条目是 0,即返回的记录。它不是说最后一个条目,而是上一个条目。
    • 对不起我的不好..删除了我的答案。
    【解决方案2】:

    我相信这应该做你想做的事

    SELECT
        T1.ID,
        T1.AuditDateTime,
        T1.UpdateType
    FROM
        dbo.My_Table T1
    INNER JOIN dbo.My_Table T2 ON
        T2.ID = T1.ID AND
        T2.UpdateType <> T1.UpdateType AND
        T2.AuditDateTime < T1.AuditDateTime
    LEFT OUTER JOIN dbo.My_Table T3 ON
        T3.ID = T1.ID AND
        T3.AuditDateTime < T1.AuditDateTime AND
        T3.AuditDateTime > T2.AuditDateTime
    WHERE
        T3.ID IS NULL
    

    或者:

    SELECT
        T1.ID,
        T1.AuditDateTime,
        T1.UpdateType
    FROM
        dbo.My_Table T1
    INNER JOIN dbo.My_Table T2 ON
        T2.ID = T1.ID AND
        T2.UpdateType <> T1.UpdateType AND
        T2.AuditDateTime < T1.AuditDateTime
    WHERE
        NOT EXISTS
        (
            SELECT *
            FROM
                dbo.My_Table T3
            WHERE
                T3.ID = T1.ID AND
                T3.AuditDateTime < T1.AuditDateTime AND
                T3.AuditDateTime > T2.AuditDateTime
        )
    

    这两个查询的基本要点是,您要查找的行是前面的行具有不同的类型,并且两行之间不存在其他行(因此,它们是连续的)。这两个查询在逻辑上是相同的,但可能具有不同的性能。

    此外,这些查询假定没有两行具有相同的审计时间。如果不是这种情况,那么您需要定义发生这种情况时您期望得到的结果。

    【讨论】:

      【解决方案3】:

      您可以使用lag() 窗口函数来查找相同ID 的先前值。现在您只能选择那些引入更改的行:

      select  *
      from    (
              select  lag(UpdateType) over (
                        partition by ID
                        order by AuditDateTime) as prev_updatetype
              ,       *
              from    YourTable
              ) sub
      where   prev_updatetype <> updatetype
      

      Example at SQL Fiddle.

      【讨论】:

      • @Andomar 我们不确定使用的是哪个版本的 SQL Server。请指定 LAG 函数在 SQL Server 2012 及更新版本中可用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-21
      相关资源
      最近更新 更多