如何生成行数多于原表的SQL输出?事件时间线场景实现
解决方案
你之前用LAG()/LEAD()搭配CASE WHEN的方案只能修改现有行的列值,无法生成额外的行,不需要纠结“在原有两行之间插入”的操作——SQL查询结果是行的集合,只要把原有事件数据和计算得到的空闲时段数据两部分用UNION ALL合并,最后按开始时间排序,就能得到你要的输出。
实现逻辑
- 第一部分查询直接取原表的事件数据,标记事件类型为
Occurrence - 第二部分用
LEAD()窗口函数拿到每条事件下一条事件的开始时间,筛选出前后事件存在间隔的记录,计算空闲时段的开始时间、时长,标记事件类型为Free Time - 两部分结果合并后按
start_time升序排序,即可得到按时间先后排列的完整结果
完整SQL代码
-- 查询原有事件行 SELECT occurs_at_time AS start_time, length, 'Occurrence' AS event_type FROM events UNION ALL -- 查询计算得到的空闲时段行 SELECT occurs_at_time + length AS start_time, next_start - (occurs_at_time + length) AS length, 'Free Time' AS event_type FROM ( SELECT occurs_at_time, length, LEAD(occurs_at_time) OVER (ORDER BY occurs_at_time) AS next_start FROM events ) t WHERE next_start IS NOT NULL -- 最后一条事件后无后续事件,不需要计算空闲 AND next_start > occurs_at_time + length -- 间隔大于0才存在有效空闲时段 -- 按时间先后排序结果 ORDER BY start_time;
结果校验
用你给出的示例数据运行上述代码:
- 事件2结束时间为
10+3=13,下一个事件3的开始时间为20,空闲时长为20-13=7,会自动生成13 | 7 | Free Time的行,最终输出和你给出的期望结果完全匹配。
内容的提问来源于stack exchange,提问作者Ricardo Francois
相关产品推荐
相关产品推荐

