我有一个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上最快的方法吗?
答案 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)
);
运行此查询一次,您将删除需要删除的大量记录,从而显示新的锚事件。继续运行它直到受影响的记录为零。此时,没有事件在前一个小时内发生事件。
我确定有一种方法来编写它,以便它可以在一个查询中工作,但这种逻辑让我感到厌烦。