删除基于日期的时间线内连续重复的值

Evi*_*lDr 5 t-sql sql-server sql-server-2012

我有一个包含基于日期的用户操作的表。该表用作事件的时间表。以下示例显示了两个人如何随着时间的推移改变其工作角色:

DECLARE @tbl TABLE (
    UserID int,
    ActionID int,
    ActionDesc nvarchar(50),
    ActionDate datetime
);
INSERT INTO @tbl (UserID, ActionID, ActionDesc, ActionDate)
VALUES 
    -- First person
    (1, 200, 'Promoted',   '2000-01-01'),   
    (1, 200, 'Promoted',   '2001-01-01'),   
    (1, 200, 'Promoted',   '2002-02-01'),   
    (1, 300, 'Moved',      '2004-03-01'),   
    (1, 200, 'Promoted',   '2005-03-01'),   
    (1, 200, 'Promoted',   '2006-03-01'),
    -- Second person
    (2, 200, 'Promoted',   '2006-01-01'),   
    (2, 300, 'Moved',      '2007-01-01'),
    (2, 200, 'Promoted',   '2008-01-01');

SELECT * FROM @tbl ORDER BY UserID, ActionDate DESC;
Run Code Online (Sandbox Code Playgroud)

这给出了以下内容,首先显示为最近的事件:

在此输入图像描述

我需要以相反的日期顺序显示表格,但根据 [UserID/ActionID] 匹配删除刚刚发生后立即发生的任何事件。例如,如果某人被晋升,然后再次晋升,则第二次晋升将不会包含在结果中,因为它会被视为与前一个操作重复。

因此,期望的输出是:

在此输入图像描述

经过研究,我试图ROW_NUMBER()识别重复项:

SELECT
    *,
    ROW_NUMBER() OVER (PARTITION BY UserID, ActionID ORDER BY ActionDate ASC) AS RowNum
FROM
    @tbl
ORDER BY
    UserID, ActionDate DESC;
Run Code Online (Sandbox Code Playgroud)

...但它不太有效,因为在每次不同的操作后编号都不会重置。我可能想得太多了,但我正在努力寻找灵感,因为搜索结果返回了无数的问题,而人们只是从列表中删除重复项。

Max*_*non 5

我会用来LEAD消除不必要的行。

\n\n
USE tempdb;\n\nDECLARE @tbl TABLE (\n    UserID int,\n    ActionID int,\n    ActionDesc nvarchar(50),\n    ActionDate datetime\n);\nINSERT INTO @tbl (UserID, ActionID, ActionDesc, ActionDate)\nVALUES \n    -- First person\n    (1, 200, \'Promoted\',   \'2000-01-01\'),   \n    (1, 200, \'Promoted\',   \'2001-01-01\'),   \n    (1, 200, \'Promoted\',   \'2002-02-01\'),   \n    (1, 300, \'Moved\',      \'2004-03-01\'),   \n    (1, 200, \'Promoted\',   \'2005-03-01\'),   \n    (1, 200, \'Promoted\',   \'2006-03-01\'),\n    -- Second person\n    (2, 200, \'Promoted\',   \'2006-01-01\'),   \n    (2, 300, \'Moved\',      \'2007-01-01\'),\n    (2, 200, \'Promoted\',   \'2008-01-01\');\n\n;WITH src AS\n(\n    SELECT *\n        , l = LEAD(t.ActionID) OVER (PARTITION BY t.UserID ORDER BY t.ActionDate DESC)\n    FROM @tbl t\n)\nSELECT src.UserID\n    , src.ActionID\n    , src.ActionDesc\n    , src.ActionDate\nFROM src\nWHERE src.l <> src.ActionID \n    OR src.l IS NULL\n
Run Code Online (Sandbox Code Playgroud)\n\n

上述查询中的子句WHERE从输出中消除重复行,其中前一行是当前行的重复 ActionID。这src.l IS NULL确保我们看到的行没有重复的 ActionID。

\n\n

结果:

\n\n
\xe2\x95\x94\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2 \x95\x90\xe2\x95\xa6\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95 \x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa6\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90 \xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2 \x95\xa6\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95 \x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90 \xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2 \x95\x90\xe2\x95\x97\n\xe2\x95\x91 用户 ID \xe2\x95\x91 操作 ID \xe2\x95\x91 操作描述 \xe2\x95\x91 操作日期 \xe2\x95\x91\n\xe2 \x95\xa0\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95 \x90\xe2\x95\xac\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90 \xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xac\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2 \x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95 \xac\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90 \xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2 \x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95 \x90\xe2\x95\xa3\n\xe2\x95\x91 1 \xe2\x95\x91 200 \xe2\x95\x91 升级 \xe2\x95\x91 2005-03-01 00:00:00.000 \xe2\ x95\x91\n\xe2\x95\x91 1 \xe2\x95\x91 300 \xe2\x95\x91 已移动 \xe2\x95\x91 2004-03-01 00:00:00.000 \xe2\x95\x91\n \xe2\x95\x91 1 \xe2\x95\x91 200 \xe2\x95\x91 升级 \xe2\x95\x91 2000-01-01 00:00:00.000 \xe2\x95\x91\n\xe2\x95\ x91 2 \xe2\x95\x91 200 \xe2\x95\x91 升级 \xe2\x95\x91 2008-01-01 00:00:00.000 \xe2\x95\x91\n\xe2\x95\x91 2 \xe2\ x95\x91 300 \xe2\x95\x91 已移动 \xe2\x95\x91 2007-01-01 00:00:00.000 \xe2\x95\x91\n\xe2\x95\x91 2 \xe2\x95\x91 200 \ xe2\x95\x91 升级 \xe2\x95\x91 2006-01-01 00:00:00.000 \xe2\x95\x91\n\xe2\x95\x9a\xe2\x95\x90\xe2\x95\x90\xe2 \x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa9\xe2\x95\x90\xe2\x95 \x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90 \xe2\x95\xa9\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2 \x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa9\xe2\x95\x90\xe2\x95\x90\xe2\x95 \x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90 \xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2 \x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x9d
\n\n

对于具有大量行的表,您希望将查询中使用的聚合数量减少到尽可能少;LEAD 只需要一个聚合即可提供此功能。我的版本的执行计划:

\n\n

在此输入图像描述

\n