基于单字段为SQL Server数据生成起止时间及关联明细行
解决SQL Server中明细行匹配表头行的问题
原始数据
| ID | StartDateTime | HeaderID |
|---|---|---|
| 1 | 2020-12-14T13:07:01.875 | 10000 |
| 2 | 2020-12-14T13:07:01.976 | 0 |
| 3 | 2020-12-14T13:07:02.496 | 0 |
| 4 | 2020-12-14T13:07:02.875 | 10001 |
| 5 | 2020-12-14T13:07:03.976 | 0 |
| 6 | 2020-12-14T13:07:04.896 | 0 |
| 7 | 2020-12-14T13:07:05.875 | 10003 |
方案1:生成每个表头的起止时间
利用SQL Server的LEAD()窗口函数,获取下一个表头的开始时间作为当前表头的结束时间,最后一个表头可自定义默认结束时间。
SELECT HeaderID, StartDateTime AS HeaderStartDateTime, LEAD(StartDateTime, 1, '2020-12-14T13:07:07.875') OVER (ORDER BY StartDateTime) AS HeaderEndDateTime FROM YourTableName WHERE HeaderID != 0 ORDER BY StartDateTime;
执行结果:
| HeaderID | HeaderStartDateTime | HeaderEndDateTime |
|---|---|---|
| 10000 | 2020-12-14T13:07:01.875 | 2020-12-14T13:07:02.875 |
| 10001 | 2020-12-14T13:07:02.875 | 2020-12-14T13:07:05.875 |
| 10003 | 2020-12-14T13:07:05.875 | 2020-12-14T13:07:07.875 |
方案2:为明细行匹配对应的表头ID
提供两种实现方式,可根据数据量选择更高效的方案:
方法1:子查询匹配
通过子查询找到每条明细行对应的、时间最近的前置表头行:
SELECT d.ID, d.StartDateTime, (SELECT TOP 1 HeaderID FROM YourTableName h WHERE h.HeaderID != 0 AND h.StartDateTime <= d.StartDateTime ORDER BY h.StartDateTime DESC) AS HeaderID FROM YourTableName d WHERE d.HeaderID = 0;
方法2:表头区间关联(大表更高效)
先生成表头的时间区间临时表,再关联明细行匹配所属区间:
WITH HeaderRanges AS ( SELECT HeaderID, StartDateTime AS StartRange, LEAD(StartDateTime, 1, '9999-12-31') OVER (ORDER BY StartDateTime) AS EndRange FROM YourTableName WHERE HeaderID != 0 ) SELECT d.ID, d.StartDateTime, hr.HeaderID FROM YourTableName d JOIN HeaderRanges hr ON d.StartDateTime >= hr.StartRange AND d.StartDateTime < hr.EndRange WHERE d.HeaderID = 0;
执行结果:
| ID | StartDateTime | HeaderID |
|---|---|---|
| 2 | 2020-12-14T13:07:01.976 | 10000 |
| 3 | 2020-12-14T13:07:02.496 | 10000 |
| 5 | 2020-12-14T13:07:03.976 | 10001 |
| 6 | 2020-12-14T13:07:04.896 | 10001 |
内容的提问来源于stack exchange,提问作者sr12345
相关产品推荐
相关产品推荐

