我编写了一个 SQL 查询来计算事件的开始和结束时间。
结果如下所示:(我将其保存为 TimeData
)
Id start end
___________________________
1 100 124
2 106 115
3 127 130
4 128 130
5 136 150
这些行按“开始”排序。
我现在想做的是折叠所有这些行以表示包含数据的时间跨度。 像这样的事情:
start end
________________
100 124
127 130
136 150
到目前为止我所完成的(但是是非常错误的)是这样的:
select * from
(select *,
LAG([end],1) over(order by [start]) as pe
from TimeData) as X
where X.pe < [start]
这实际上适用于一些后续行,但它使 pe
与 TimeData
中的前一行保持一致,而我要求它来自上一个返回行(上一行,其中条件为真)。
我希望我的问题很清楚。 如有任何帮助,我们将不胜感激。
最佳答案
您的问题看起来像 Itzik Ben-Gan 称为 Packing Intervals 的问题。在他的文章中,他展示了一种比另一个答案中显示的自连接更有效的方法。
有关其工作原理的详细说明,请参阅他的文章。逐步、逐个 CTE 运行查询并检查中间结果以了解其工作原理。
示例数据
DECLARE @T TABLE(ID int, starttime int, endtime int);
INSERT INTO @T VALUES
(1, 100, 124),
(2, 106, 115),
(3, 127, 130),
(4, 128, 130),
(5, 136, 150);
查询
WITH
C1 AS
(
SELECT ID, starttime AS ts, +1 AS type, 1 AS sub
FROM @T
UNION ALL
SELECT ID, endtime AS ts, -1 AS type, 0 AS sub
FROM @T
)
,C2 AS
(
SELECT C1.*,
SUM(type)
OVER(ORDER BY ts, type DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
- sub AS cnt
FROM C1
)
,C3 AS
(
SELECT ID, ts,
(ROW_NUMBER() OVER(ORDER BY ts) - 1) / 2 + 1
AS grpnum
FROM C2
WHERE cnt = 0
)
SELECT MIN(ts) AS starttime, MAX(ts) AS endtime
FROM C3
GROUP BY grpnum;
结果
+-----------+---------+
| starttime | endtime |
+-----------+---------+
| 100 | 124 |
| 127 | 130 |
| 136 | 150 |
+-----------+---------+
关于sql - 基于 LAG 列(打包间隔)跳过行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47166900/