从表中删除close(及时)行

时间:2014-12-12 22:05:33

标签: sql time

我有一个SQL表Tb,如:

ID      EventDate
18179   2014-11-12 10:18:08.0
18179   2014-12-12 09:41:02.0
18179   2014-12-12 10:26:03.0
18179   2014-12-12 10:28:00.0
18179   2014-12-12 11:17:36.0
18179   2014-12-12 12:17:45.0
18179   2014-12-12 12:17:56.0
262070  2014-11-12 11:30:00.0
262070  2014-11-12 11:33:26.0
262070  2014-12-12 10:17:19.0
262070  2014-12-12 11:33:26.0

我需要为每个ID执行网格删除:通过从最近开始的一小时内从Tb中删除那些行来创建新表。 在那种特殊情况下,我的表Tb_new应该看起来像

ID      EventDate
18179   2014-11-12 10:18:08.0
18179   2014-12-12 09:41:02.0
18179   2014-12-12 11:17:36.0
18179   2014-12-12 12:17:56.0
262070  2014-11-12 11:33:26.0
262070  2014-12-12 10:17:19.0
262070  2014-12-12 11:33:26.0

原始表格很大(数百万或行,100K + ID)。 有人可以帮助我找到在SQL上最快的方法吗?

1 个答案:

答案 0 :(得分:1)

这看起来像是家庭作业,但这就是我的工作方式。

首先,找到的所有EventDates在上一个小时内有另一个具有相同ID的事件:

select *
from #Tb anchor
where not exists (
    select 1
    from #Tb base
    where base.ID = anchor.ID
        and base.EventDate < anchor.EventDate
        and base.EventDate >= dateadd(hh,-1,anchor.EventDate)
    );

这是您的锚定事件,因为缺少更好的术语。你知道你想要保留这些事件的事实。主播事件已知好

现在,删除锚定事件后不到一小时发生的任何事件:

delete invalid
from #Tb invalid
where exists (
    select 1
    from #Tb anchor
    where not exists (
        select 1
        from #Tb base
        where base.ID = anchor.ID
            and base.EventDate < anchor.EventDate
            and base.EventDate >= dateadd(hh,-1,anchor.EventDate)
        )
        and invalid.ID = anchor.ID
        and invalid.EventDate > anchor.EventDate
        and invalid.EventDate <= dateadd(hh,1,anchor.EventDate)
    );

运行此查询一次,您将删除需要删除的大量记录,从而显示新的锚事件。继续运行它直到受影响的记录为零。此时,没有事件在前一个小时内发生事件。

我确定有一种方法来编写它,以便它可以在一个查询中工作,但这种逻辑让我感到厌烦。