Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 基于滞后列跳过行(打包间隔)_Sql_Sql Server - Fatal编程技术网

Sql 基于滞后列跳过行(打包间隔)

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

我编写了一个SQL查询来计算事件的开始和结束时间。 结果如下:我将其保存为TimeData

这些行按“开始”排序

我现在要做的是折叠所有这些行,以表示包含数据的时间跨度。 大概是这样的:

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 |
+-----------+---------+