基于具有重复出现模式的时间戳对表进行重复数据删除

发布于 2024-10-29 01:03:51 字数 1006 浏览 4 评论 0原文

好的。首先,如果这个问题已经被提及,请允许我深表歉意。我确实查看过,但没有一个解决方案能够解决我的问题的具体情况。

我有一个包含超过 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 - 抱歉没有提及。

Ok. First let me apologize profusely if this question has been covered. I did look but none of the solutions addressed the particulars of my problem.

I have a table of over 160 million rows of data tracking employee/server conditions over time. I want to create a subset of this data and remove the repetition that occurs throughout, BUT keeps the sequence of changes as they occur. The reduction for most employees would be from 700 rows (and growing) to 1.

Here's a simplified example of what I'm trying to get to:

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

The table and the process that feeds it do not belong to our group so I can't affect a solution there and I'd rather not be stuck with a copy of the entire thing. I can't realistically do a cursor/RBAR approach given the size of the table. If backed into a corner, I can write an application program to do this but I was wondering if any of the gods from SQoLympus had any wisdom for doing this in a stored procedure. Thanks in advance!

Edit: It's SQL Server 2008 - Sorry for not mentioning it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

吝吻 2024-11-05 01:03:51

如果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

If SQL Server (assuming I have understood your requirements correctly)

/*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
悲歌长辞 2024-11-05 01:03:51

您没有说明您正在使用什么数据库,但如果例如这是 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)

You didn't say what DB you're using, but if for example this is Oracle, you can use the lag or lead analytic functions to reference the previous or next row.

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文