我认为满足要求的最佳方法是使用DATEDIFF、FIRST_VALUE 和整数数学的组合将微小差异除以 30 分钟。这会在 HashID 窗口分区内创建不同的 30 分钟会话分组。只需要一个 CTE。
数据(类似于seanb)
drop table if exists #DeviceLoads;
go
create table #DeviceLoads (
LogID int identity(1,1),
HashID nvarchar(10),
DeviceDatetime datetime);
insert into #DeviceLoads (HashID, DeviceDatetime) values
('ID1', '20201013 15:26'),
('ID1', '20201013 15:26'),
('ID1', '20201013 15:28'),
('ID1', '20201013 15:28'),
('ID1', '20201013 15:28'),
('ID1', '20201014 14:59'),
('ID1', '20201014 14:59'),
('ID1', '20201014 16:17'),
('ID1', '20201014 16:46'),
('ID1', '20201014 17:15'),
('ID1', '20201014 17:46'),
('ID2', '20201014 14:59'),
('ID2', '20201014 16:17'),
('ID2', '20201014 16:27'),
('ID2', '20201014 16:37'),
('ID2', '20201014 16:46'),
('ID3', '20201014 17:15'),
('ID3', '20201014 17:46');
查询
with session_cte as (
select *, datediff(minute, first_value(DeviceDatetime) over
(partition by HashID order by DeviceDatetime),
DeviceDatetime)/30 Session_Num
from #DeviceLoads)
select Session_Num,
HashID,
count(*) AS Num_Actions,
min(DeviceDateTime) AS First_Action,
max(DeviceDateTime) AS Last_Action
from session_cte
group by Session_Num, HashID;
查询以分钟为单位获取每个 HashID 的平均会话
with
session_cte as (
select *, datediff(minute, first_value(DeviceDatetime) over
(partition by HashID order by DeviceDatetime),
DeviceDatetime)/30 Session_Num
from #DeviceLoads),
hash_cte as (
select Session_Num,
HashID,
count(*) AS Num_Actions,
min(DeviceDateTime) AS First_Action,
max(DeviceDateTime) AS Last_Action
from session_cte
group by Session_Num, HashID)
select HashID, avg(datediff(minute, First_Action, Last_Action)*1.0) avg_session_min
from hash_cte
group by HashID;
输出
HashID avg_session_min
ID1 0.333333
ID2 6.333333
ID3 0.000000