按日期范围对行进行分组
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
我想知道在特定秒数(例如 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