【问题标题】:De-dupe a table based on timestamp with reoccuring patterns基于重复出现模式的时间戳对表进行重复数据删除
【发布时间】:2011-04-02 19:20:46
【问题描述】:

好的。如果这个问题已经涵盖,首先让我深表歉意。我确实看过,但没有一个解决方案解决了我的问题的细节。

我有一个包含超过 1.6 亿行数据的表,用于跟踪员工/服务器的状况。我想创建这个数据的一个子集并删除整个过程中发生的重复,但是在发生变化时保持变化的顺序。大多数员工的减少量将从 700 行(并且还在增加)减少到 1 行。

这是我想要达到的简化示例:

Given:

RowID  Employee  Server  Timestamp
-----  --------  ------  ---------
5      E000001   Serv-B  May01
4      E000001   Serv-A  Apr01
3      E000001   Serv-B  Mar01
2      E000001   Serv-A  Feb01
1      E000001   Serv-A  Jan01

Doing a "Min(Timestamp) Group By Employee, Server" would yield:
Employee Server  Timestamp
-------- ------  ---------
E000001  Serv-B  Mar01
E000001  Serv-A  Jan01
.
What I need is:
Employee Server  Timestamp
-------- ------  ---------
E000001  Serv-B  May01
E000001  Serv-A  Apr01
E000001  Serv-B  Mar01
E000001  Serv-A  Jan01

表格和为其提供数据的进程不属于我们的小组,因此我不能影响那里的解决方案,我宁愿不被整个事情的副本所困扰。考虑到表格的大小,我实际上无法执行游标/RBAR 方法。如果退缩,我可以编写一个应用程序来执行此操作,但我想知道是否有任何来自 SQoLympus 的神有智慧在存储过程中执行此操作。提前致谢!

编辑:这是 SQL Server 2008 - 抱歉没有提及。

【问题讨论】:

  • 什么 RDBMS 和版本? Timestamp 是什么数据类型?

标签: sql tsql sql-server-2008 duplicates sequence


【解决方案1】:

如果 SQL Server(假设我正确理解了您的要求)

/*Set up test table*/
DECLARE @T TABLE (
  RowID       INT,
  Employee    CHAR(7),
  [Server]    CHAR(6),
  [timestamp] DATETIME );

INSERT INTO @T
SELECT 5,'E000001','Serv-B',  '20010501' UNION ALL
SELECT 4,'E000001','Serv-A',  '20010401' UNION ALL
SELECT 3,'E000001','Serv-B',  '20010301' UNION ALL
SELECT 2,'E000001','Serv-A',  '20010201' UNION ALL
SELECT 1,'E000001','Serv-A',  '20010101';

WITH cte
     As (SELECT ROW_NUMBER() OVER (PARTITION BY Employee ORDER BY RowID) -
                ROW_NUMBER() OVER (PARTITION BY Employee, Server
                                       ORDER BY RowID) AS Grp,
                *
         FROM   @T),
     cte2
     AS (SELECT *,
                ROW_NUMBER() OVER (PARTITION BY Employee, Grp ORDER BY RowID) AS
                Rn
         FROM   cte)

/* Edit: Actually - You want a SELECT not a DELETE I think?
DELETE FROM cte2 WHERE  Rn > 1*/

SELECT   RowID, Employee, [Server], [timestamp]
FROM cte2
WHERE  Rn = 1

【讨论】:

  • 绝对是 SQoLympus 的神之一!非常感谢!
【解决方案2】:

您没有说您使用的是什么数据库,但如果这是 Oracle,您可以使用 laglead 分析函数来引用上一行或下一行。

select employee, server, timestamp 
from
   (select employee, server, timestamp,
    lag(employee) over (order by employee, server, timestamp) prev_employee 
    lag(server) over (order by employee, server, timestamp) prev_server 
    from table
   )
where not (employee = prev_employee and server = prev_server)

【讨论】:

  • 不幸的是,这些函数还没有进入 SQL Server。
猜你喜欢
  • 2022-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-29
  • 2021-11-15
  • 2020-11-03
  • 2018-07-15
  • 2020-05-26
相关资源
最近更新 更多