sql - 基于 LAG 列(打包间隔)跳过行

标签 sql sql-server

我编写了一个 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]

这实际上适用于一些后续行,但它使 peTimeData 中的前一行保持一致,而我要求它来自上一个返回行(上一行,其中条件为真)。

我希望我的问题很清楚。 如有任何帮助,我们将不胜感激。

最佳答案

您的问题看起来像 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/

相关文章:

SQL Oracle 约束值在多个列中唯一

java - 比较两个表中的值

php - 我如何用mysqli写这个?

php - MySql Select 语句不起作用

sql - Postgres 区分大小写

c# - LINQ 中的查询比 SQL 更复杂

c# - 如何将sql inner join query转成linq to sql query并转成list

php - 无法从 php 将 ids 添加到 mysql 中的字段

sql - 存储过程不返回任何行,但相同的查询返回正确的数据

mysql - SQL查询内连接得到2个项目