我有一个记录某些用户事件的数据表。结果看起来像:
ID Username EventDate
1 UserA 2010-10-21 16:59:59.367
2 UserA 2010-10-21 17:00:00.114
3 UserA 2010-10-21 17:00:00.003
4 UserA 2010-10-21 17:00:02.867
5 UserB 2010-10-21 18:43:26.538
6 UserB 2010-10-21 18:47:33.373
我想运行一个查询,删除在上一个事件的3000毫秒内发生的所有事件。请注意,毫秒是相关的。
结果表格如下:
ID Username EventDate
1 UserA 2010-10-21 16:59:59.367
4 UserA 2010-10-21 17:00:02.867
5 UserB 2010-10-21 18:43:26.538
6 UserB 2010-10-21 18:47:33.373
我该怎么做?
答案 0 :(得分:2)
您可以使用while
循环一次删除一行。这样可以避免多行在3秒内完成,但不会在第一行的3秒内出现的问题。
例如:
declare @t table (ID int, Username varchar(50), EventDate datetime)
insert @t
select 1, 'UserA', '2010-10-21 16:59:59.367'
union all select 2, 'UserA', '2010-10-21 17:00:00.114'
union all select 3, 'UserA', '2010-10-21 17:00:00.003'
union all select 4, 'UserA', '2010-10-21 17:00:02.867'
union all select 5, 'UserB', '2010-10-21 18:43:26.538'
union all select 6, 'UserB', '2010-10-21 18:47:33.373'
while 1=1
begin
delete @t
where ID =
(
select top 1 t2.ID
from @t t2
where exists
(
select *
from @t t1
where t1.Username = t2.Username
and t1.EventDate < t2.EventDate
and datediff(millisecond, t1.EventDate,
t2.EventDate) <= 3000
)
)
if @@ROWCOUNT = 0
break
end
select * from @t
打印:
ID Username EventDate
1 UserA 2010-10-21 16:59:59.367
4 UserA 2010-10-21 17:00:02.867
5 UserB 2010-10-21 18:43:26.537
6 UserB 2010-10-21 18:47:33.373
答案 1 :(得分:1)
如果我们从结果集中删除这些结果,并且每个用户事件都是单独处理的,那么以下工作(从Andomar的答案中窃取表格):
declare @t table (ID int, Username varchar(50), EventDate datetime)
insert @t
select 1, 'UserA', '2010-10-21 16:59:59.367'
union all select 2, 'UserA', '2010-10-21 17:00:00.114'
union all select 3, 'UserA', '2010-10-21 17:00:00.003'
union all select 4, 'UserA', '2010-10-21 17:00:02.867'
union all select 5, 'UserB', '2010-10-21 18:43:26.538'
union all select 6, 'UserB', '2010-10-21 18:47:33.373'
;WITH PerUserIDs AS (
SELECT ID,Username,EventDate,ROW_NUMBER() OVER (PARTITION BY Username ORDER BY EventDate) as R from @t
), Sequenced AS (
SELECT ID,Username,EventDate,R from PerUserIDs where R = 1
union all
select pui.ID,pui.UserName,pui.EventDate,pui.R
from
Sequenced s
inner join
PerUserIDs pui
on
s.R < pui.R and
s.Username = pui.Username and
DATEDIFF(millisecond,s.EventDate,pui.EventDate) >= 3000
where
not exists(select * from PerUserIDs anti where anti.R < pui.R and s.R < anti.R and s.Username = anti.username and DATEDIFF(millisecond,s.EventDate,anti.EventDate)>= 3000)
)
select * from Sequenced order by Username,EventDate
如果你确实需要删除,那么你可以从你的表中删除ID不在的表(从Sequenced中选择ID)
答案 2 :(得分:0)
以前的活动,你的意思是插入?为什么不把时间线作为基础?
答案 3 :(得分:0)
您可以通过按日期顺序迭代事件并使用DATEDIFF将前一事件的值与当前事件的值进行比较来编写一个过程来执行此操作。如果这是一个活动系统,并且您的目标是防止重复事件日志,那么使用触发器来阻止以类似方式插入任何新事件会更有意义。