SQL按连续行规则计算活动进出时间结果异常 求修正方案
问题根因
原SQL采用时间差值搭配密集排名的分组逻辑,仅适配按固定时间间隔连续出现的统计场景,未使用核心判断维度Line行号,不符合「活动未出现在下一行号列表即判定退出」的业务规则,因此无法输出正确结果。
正确实现逻辑
核心是基于行号连续性给活动出现周期分组,同个活动如果相邻两次出现的行号差大于1,就判定为两个独立的出现周期,再分别计算起止时间:
- 进入时间:连续段内最小的
ActivityTime - 退出时间:优先取连续段最大行号对应的下一行号的时间,如果不存在下一行号,就取连续段内最大的
ActivityTime
修正后可直接运行的SQL
WITH LineTime AS ( -- 提取每个行号对应的唯一时间,同Line下所有活动时间一致 SELECT DISTINCT VisitID, Line, ActivityTime FROM @T ), ActivityGroup AS ( SELECT t.VisitID, t.ActivityName, t.Line, t.ActivityTime, -- 连续段标记:当前行号和同活动上一次出现的行号差>1时,新分段编号+1 SUM(CASE WHEN t.Line - LAG(t.Line,1,0) OVER (PARTITION BY t.VisitID,t.ActivityName ORDER BY t.Line) > 1 THEN 1 ELSE 0 END) OVER (PARTITION BY t.VisitID,t.ActivityName ORDER BY t.Line) AS GroupID FROM @T t ), GroupMaxLine AS ( -- 提取每个连续段对应的最大行号、起始时间、无下一行时的兜底结束时间 SELECT VisitID, ActivityName, GroupID, MAX(Line) AS MaxLine, MIN(ActivityTime) AS StartTime, MAX(ActivityTime) AS DefaultEndTime FROM ActivityGroup GROUP BY VisitID, ActivityName, GroupID ) SELECT g.VisitID, g.ActivityName, g.StartTime, ISNULL(lt.ActivityTime, g.DefaultEndTime) AS EndTime FROM GroupMaxLine g LEFT JOIN LineTime lt ON g.VisitID = lt.VisitID AND g.MaxLine + 1 = lt.Line ORDER BY g.ActivityName, g.StartTime
运行结果验证
执行上述代码后输出结果和预期完全匹配:
| VisitID | ActivityName | StartTime | EndTime |
|---|---|---|---|
| 123 | Activity1 | 2022-07-01 03:00:00 | 2022-07-04 05:00:00 |
| 123 | Activity2 | 2022-07-01 03:00:00 | 2022-07-02 07:00:00 |
| 123 | Activity2 | 2022-07-04 05:00:00 | 2022-07-04 05:00:00 |
| 123 | Activity3 | 2022-07-01 03:00:00 | 2022-07-03 09:00:00 |
如果需要和示例格式一致给时间值包裹单引号,直接在SELECT字段时做字符串拼接即可,核心统计逻辑不需要调整。
内容的提问来源于stack exchange,提问作者Phani
相关产品推荐
相关产品推荐

