查找它们之间具有特定时间增量的行

时间:2014-12-12 10:39:15

标签: sql algorithm time

通常,我的任务是这样的:不同的动作有很多ID和时间戳。我注意找到那些ID

中的ID

A1,A1,A2,A3,...,An

存在Ai,Al和Am(1 <= i,l,m <= n),1小时&lt; = timediff(Ai,Al)&lt; = 1周和1小时&lt; = timediff(Al ,Am)&lt; = 1周。 这里A表示行动的时间。

特别是,我有数据(如下所示),并且只想找到以下陈述为真的ID:同一个ID,3个动作之间至少1小时,两个动作之间不超过1周。

ID      EventDate
6727    2014-12-12 09:41:02.0
17390   2014-12-12 10:06:03.0
18179   2014-11-12 10:18:08.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 11:33:26.0
262070  2014-12-12 10:17:19.0

例如,对于那个例子,它可能是18179(因为我可以在那里找到3个动作:10:06:03.0,11:17:36.0和12:17:56.0)但不是262070(因为没有3个动作在1小时到1周的日志中。)

有人可以帮助我以最方便的SQL方式做到这一点,但没有存储过程。

2 个答案:

答案 0 :(得分:1)

你试过这样的事吗

SELECT Start.ID FROM 
Table AS Start
INNER JOIN Table AS Middle ON  Start.ID = Middle.ID AND DATEDIFF( hour, Start.EventDate,Middle.EventDate) > 1 AND DATEDIFF( week , Start.EventDate,Middle.EventDate) < 1
INNER JOIN Table AS End ON  Start.ID = Middle.ID AND DATEDIFF( hour, End .EventDate,Middle.EventDate) > 1 AND DATEDIFF( week , End .EventDate,Middle.EventDate) < 1
WHERE Start.ID IS NOT NULL AND Middle.ID IS NOT NULL AND End .ID IS NOT NULL

答案 1 :(得分:1)

试试这个。如果不清楚,请在评论中提问。

declare @example table (
    action_id int,
    action_date datetime
)

insert @example (action_id, action_date)
select 6727,    '2014-12-12 09:41:02.0' union all
select 17390,   '2014-12-12 10:06:03.0' union all
select 18179,   '2014-11-12 10:18:08.0' union all
select 18179,   '2014-12-12 10:17:36.0' union all
select 18179,   '2014-12-12 12:17:45.0' union all
select 18179,   '2014-12-12 11:17:26.0' union all
select 262070,  '2014-11-12 11:30:00.0' union all
select 262070,  '2014-11-12 11:33:26.0' union all
select 262070,  '2014-12-12 11:33:26.0' union all
select 262070,  '2014-12-12 10:17:19.0'

select distinct e.action_id
from (select action_id
        from @example
        group by action_id) e
    cross apply (select e1.action_date
                    from @example e1
                    where e1.action_id = e.action_id) ee1
    cross apply (select e2.action_date
                    from @example e2
                    where e2.action_id = e.action_id) ee2
    cross apply (select e3.action_date
                    from @example e3
                    where e3.action_id = e.action_id) ee3
where ee1.action_date<ee2.action_date and
        ee2.action_date<ee3.action_date and
        datediff(hour,ee1.action_date, ee3.action_date) between 1 and 24*7
group by e.action_id