按日期范围对行进行分组

Group Rows By Date Range

我想知道在特定秒数(例如 10 秒)内,某个用户有多少行。因此,鉴于此数据:

UserId  CreatedDate
4.........2017-01-11 01:40:19:077
4.........2017-01-11 01:40:19:437
4.........2017-01-11 01:40:20:077
4.........2017-01-11 01:50:19:077
4.........2017-01-11 02:40:19:077
4.........2017-01-11 02:40:19:437
4.........2017-01-11 02:40:20:077
4.........2017-01-11 02:40:20:437
4.........2017-01-11 02:40:21:077
4.........2017-01-11 02:40:22:077
4.........2017-01-11 02:40:23:077
4.........2017-01-11 03:15:19:077
4.........2017-01-11 03:40:19:077
4.........2017-01-11 04:40:19:077

前三行将被组合在一起,第 5-11 行将被组合在一起(因为它们之间的间隔都在 10 秒以内)。

我尝试过类似的方法,但这只会给我以两个为一组的行。我想知道 10 秒范围内的所有行。

;WITH CTE AS
(
    SELECT UserId
        ,CreatedDate
        ,ISNULL(LAG(CreatedDate) OVER (Partition BY UserId ORDER BY CreatedDate), '1/1/2000') AS PriorCreatedDate
    FROM Foo
)
SELECT *
FROM CTE
WHERE DATEDIFF(SECOND,PriorCreatedDate,CreatedDate) <= 1
ORDER BY UserId, CreatedDate

这可能吗?

也许沿着这些思路...

例子

Declare @YourTable Table ([UserId] int,[CreatedDate] datetime)
Insert Into @YourTable Values 
 (4,'2017-01-11 01:40:19:077')
,(4,'2017-01-11 01:40:19:437')
,(4,'2017-01-11 01:40:20:077')
,(4,'2017-01-11 01:50:19:077')
,(4,'2017-01-11 02:40:19:077')
,(4,'2017-01-11 02:40:19:437')
,(4,'2017-01-11 02:40:20:077')
,(4,'2017-01-11 02:40:20:437')
,(4,'2017-01-11 02:40:21:077')
,(4,'2017-01-11 02:40:22:077')
,(4,'2017-01-11 02:40:23:077')
,(4,'2017-01-11 03:15:19:077')
,(4,'2017-01-11 03:40:19:077')
,(4,'2017-01-11 04:40:19:077')

;with cte as (
    Select *
          ,Flg = case when datediff(SECOND,lag(CreatedDate,1,CreatedDate) over (Partition By UserID Order by CreatedDate),CreatedDate ) >=10 then 1 else 0 end
     From @YourTable
) 
Select UserID
      ,DateR1 = min(CreatedDate)
      ,DateR2 = max(CreatedDate)
      ,RecCnt = sum(1)
 From (Select *,Grp=sum(Flg) over (partition by UserID order by CreatedDate) From  cte ) A
 Group by UserID,Grp

Returns

UserID  DateR1                      DateR2                      RecCnt
4       2017-01-11 01:40:19.077     2017-01-11 01:40:20.077     3
4       2017-01-11 01:50:19.077     2017-01-11 01:50:19.077     1
4       2017-01-11 02:40:19.077     2017-01-11 02:40:23.077     7
4       2017-01-11 03:15:19.077     2017-01-11 03:15:19.077     1
4       2017-01-11 03:40:19.077     2017-01-11 03:40:19.077     1
4       2017-01-11 04:40:19.077     2017-01-11 04:40:19.077     1

EDIT - Requested Notes

如果你要执行

;with cte as (
    Select *
          ,Flg = case when datediff(SECOND,lag(CreatedDate,1,CreatedDate) over (Partition By UserID Order by CreatedDate),CreatedDate ) >=10 then 1 else 0 end
     From @YourTable
) 
Select *
      ,Grp=sum(Flg) over (partition by UserID order by CreatedDate) 
From  cte   

结果将是:

注意 Flg 和 Grp 列。 Grp 列本质上是 Flg 列的 运行 总数。

这种方式有更多的性能:

SELECT UserId, Date = Min( --Min or any value in the group give the same value
    case when DATEDIFF(SECOND, PreviousDate, creationDate) <= 10 
        then creationDate
        else PreviousDate
        end
)

FROM (
SELECT *,
PreviousDate = LAG(CreatedDate, 1, CreatedDate) OVER (Partition BY UserId ORDER BY CreatedDate desc), 
FROM CTE
)

GROUP BY UserId, case when DATEDIFF(SECOND, PreviousDate, creationDate) <= 10 
        then creationDate
        else PreviousDate
        end
ORDER BY UserId, Date