Sql 基于滞后列跳过行(打包间隔)
我编写了一个SQL查询来计算事件的开始和结束时间。 结果如下:我将其保存为TimeData 这些行按“开始”排序 我现在要做的是折叠所有这些行,以表示包含数据的时间跨度。 大概是这样的:Sql 基于滞后列跳过行(打包间隔),sql,sql-server,Sql,Sql Server,我编写了一个SQL查询来计算事件的开始和结束时间。 结果如下:我将其保存为TimeData 这些行按“开始”排序 我现在要做的是折叠所有这些行,以表示包含数据的时间跨度。 大概是这样的: start end ________________ 100 124 127 130 136 150 select * from (select *, LAG([end],1) over(order by [start]) as pe from Ti
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]
到目前为止,我所取得的成就,但却大错特错,是这样的:
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中的前一行,而我要求它来自前一个返回行,前一行的条件为true
我希望我的问题是清楚的。
非常感谢您的帮助。非常痛苦。一种方法是确定哪些记录开始一个新的间隔。您必须小心延迟,因为重叠可能不在前一条记录上 这里有一种方法:
with t as (
select t.*,
(case when exists (select 1
from t t2
where t.start <= t2.end and t.start >= t2.start and
t2.id < t.id
)
then 0 else 1
end) as startgrp
from t
)
select grp, min(start), max(end)
from (select t.*, sum(startgrp) over (order by start) as grp
from t
) t
group by grp;
你的问题看起来就像伊兹克·本·甘所说的问题。在他的文章中,他展示了一种比另一个答案中显示的自连接更有效的方法 有关其工作原理的详细说明,请参见他的文章。一步一步地运行查询,逐个CTE并检查中间结果以了解其工作原理 样本数据 质疑 结果
我会尽快试一试。将答复:thanks@AliJey,你的问题看起来就像伊兹克·本·甘所说的问题。在他的文章中,他展示了一种比此答案中所示的自连接更有效的方法。如果在同一天存在连接日期,此方法可能会出现问题。您好@GordonLinoff,您能否给出一个导致查询结果不正确的示例。我不太明白你说的同一天是什么意思。开始和结束都是int。如果需要,请随意编辑我的答案。谢谢,很简单。如果100/124重复两次,则不能保证最终和为零。SQL中的排序不稳定,结果也不必一致,从一行到下一行都是事件。同样,100/101和101/102的结果可能不一致。对不起,@GordonLinoff,我还是不明白。你说的是由ts,DESC…订购的SUMtype吗?它将合并所有重叠的间隔。如果有两个间隔[100,101和[101,102],它们将合并为一个[100,102。保证。假设间隔是闭合的-打开的。我认为,按ts排序,类型DESC足以保证正确的运行总数,即使起始和/或结束值重复。具体而言,类型DESC很重要。
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 |
+-----------+---------+