如何使此查询聚合时间分组正确?

时间:2014-01-30 22:28:52

标签: sql sql-server aggregate-functions

我尝试根据字符串和事件时间执行基于行的分组。必须在30分钟内将相同的字符串与事件时间的出现进行分组。如果事件时间之间的时间超过30分钟,则会有一个新的组。

到目前为止,我发现了以下尝试(许多类似的,但这是最简单的)。通过下面的评论,我也注意到我错过了它的作用。它进行了30分钟的舍入,这不能满足我的需要。也许“基于'在日期范围内'的分组”更具说服力?

SELECT  min(eventtime) as mintime, 
        max(eventtime) as maxtime, 
        [stringfield],
        count([stringfield]) as qty
FROM Searches
GROUP BY datediff(mi, '19900101', eventtime) / 30, 
         [stringfield]
ORDER BY min(eventtime)

导致此表​​格 enter image description here

请参阅红色和蓝色箭头。这两行应该汇总。红色箭头表示“相同的字符串”。蓝色箭头表示“最长时间在30分钟范围内”。

在> =问题的情况下,我也尝试了31分钟没有成功。有人能看到这个T-SQL为什么会出错?我怎么解决它?

[编辑]
预期输出是带箭头分组的两行。这意味着我期望输出中有五行。第5行不应存在(汇总到第一行)。这导致第一行的数量为3,maxtime将为'2013-06-01 08:55'。

2013-06-01 08:00 | 2013-06-01 08:55 | 0x2BBF4........26BD38 | 3

1 个答案:

答案 0 :(得分:3)

在2012版的SQL-Server中,您可以使用分析LAG()LEAD()函数:

; WITH cte AS
  ( SELECT
        stringfield
      , eventtime
      , rn = ROW_NUMBER() OVER ( PARTITION BY stringfield
                                 ORDER BY eventtime )
      , leadtime = LEAD(eventtime) OVER ( PARTITION BY stringfield
                                          ORDER BY eventtime )
      , firsttime= MIN(eventtime) OVER ( PARTITION BY stringfield )
      , diff = CASE WHEN DATEADD(minute, 30, eventtime)
                         >= LEAD(eventtime) 
                            OVER ( PARTITION BY stringfield
                                   ORDER BY eventtime )
                    THEN 0 ELSE 1
               END 
    FROM 
        Searches
  ) 
SELECT 
    stringfield
  , mintime = COALESCE(LAG(leadtime) OVER ( PARTITION BY stringfield
                                            ORDER BY eventtime )
               ,firsttime) 
  , maxtime = eventtime 
  , qty = rn - COALESCE(LAG(rn) OVER ( PARTITION BY stringfield
                                       ORDER BY eventtime ) 
                       ,0)
FROM 
    cte 
WHERE 
    diff = 1
ORDER BY 
    stringfield,
    maxtime ;

经过 SQL-Fiddle 测试。