COUNT(*)组由类似的时间戳组成

时间:2018-04-08 09:34:56

标签: sql sql-server tsql group-by

我的表格中有一些数据(tb1):

PK   datetime1               datetime2               grp
--------------------------------------------------------
 1   2016-01-01 00:30:10     2016-01-01 00:33:10      1
 2   2013-01-01 00:30:10     2013-01-01 00:34:10      2

我正在尝试根据datetime1,datetime2和location查找事件数。

所以这是我的问题:

 select count(*), datetime1, datetime2, grp 
 from tb1
 group by datetime1, datetime2, grp

这里没问题。

在某种程度上,我想基于以下方式找到计数:

当两个连续的(可以通过引导函数实现)行的datetime1差异小于1秒并且两个连续行之间的datetime2差异小于1秒,并且grp。

我可以使用lead来查找两个连续行之间的差异,但不知道如何在此处应用count函数来按两个连续行之间的时间相似性进行分组。

为了使这更简单,我正在寻找这样的东西:

如果

 select 
     count(*), grp, ....
 from 
     tb1
 where 
     datediff(s, lead(datetime1, 1, 1)  over (partition by grp order by datetime1)) = 1 
     and datediff(s, lead(datetime2, 1, 1) = 1 over (partition by grp order by datetime2) = 1 
group by
    lead(datetime1, 1, 1) over (partition by grp order by datetime1), 
    lead(datetime2, 1, 1) over (partition by grp order by datetime2), 
    grp 

如果需要进一步澄清,请告诉我。

2 个答案:

答案 0 :(得分:2)

我生成了一些示例数据。检查这是否是您要找的。我在代码中添加了必要的注释。查询可以更简洁,但我想尽可能多地解释每一步:

declare @table table (PK int, datetime1 datetime, datetime2 datetime, grp int)
insert into @table values
(1, '2016-01-01 00:30:14.000', '2016-01-01 00:33:15.000', 1),
(2, '2016-01-01 00:30:10.232', '2016-01-01 00:33:10.000', 1),
(3, '2016-01-01 00:30:10.111', '2016-01-01 00:33:10.234', 1),
(4, '2016-01-01 00:30:12.000', '2016-01-01 00:33:15.000', 2),
(5, '2016-01-01 00:30:10.000', '2016-01-01 00:33:10.234', 2),
(6, '2016-01-01 00:30:10.222', '2016-01-01 00:33:10.000', 2)

select min(pk), min(datetime1), count(*) from (
    --in this query, based on differences, we will generate grouping column called IsClose
    select *, case when (diff1 <= 1000 and diff2 <= 1000) or (diff3 <= 1000 and diff4 <= 1000) then 1 else 0 end [IsClose] from (
        --this query gives to additionals columns with absolute differences between consecutive rows ordered by PK column
        select *,
               abs(datediff(ms, datetime1, lag(datetime1) over (order by pk))) [diff1],
               abs(datediff(ms, datetime2, lag(datetime2) over (order by pk))) [diff2],
               abs(datediff(ms, datetime1, lead(datetime1) over (order by pk))) [diff3],
               abs(datediff(ms, datetime2, lead(datetime2) over (order by pk))) [diff4]  
        from @table
    ) [a]
) [a] group by grp, IsClose

答案 1 :(得分:2)

这是基于int的,但同样的方法适用于datetime

declare @T table (pk int identity primary key, val int);
insert into @T values ('1'), ('9'), ('9'), ('11'), ('2'), ('2'), ('3'), ('5'), ('7'), ('8');
select tt.pk, tt.val 
     , sum(ll) over (order by val, pk) as grp
from  ( select * 
             , case when lag(val,1) over (order by val, pk) is null 
                      or val - lag(val,1) over (order by val, pk) <= 1 then 0 
                    else 1 
               end as ll
          from @T t
      ) tt
order by val, pk;

pk          val         grp
----------- ----------- -----------
1           1           0
5           2           0
6           2           0
7           3           0
8           5           1
9           7           2
10          8           2
2           9           2
3           9           2
4           11          3