如何巩固时间块?

Jaa*_*ole 8 sql t-sql sql-server

我有一个派生表,其中包含外键(ID)的相对秒数列表:

CREATE TABLE Times (
    ID INT
  , TimeFrom INT
  , TimeTo INT
);
Run Code Online (Sandbox Code Playgroud)

该表主要包含非重叠数据,但有时候我有另一条记录的TimeTo <TimeFrom:

+----+----------+--------+
| ID | TimeFrom | TimeTo |
+----+----------+--------+
| 10 | 10       | 30     |
| 10 | 50       | 70     |
| 10 | 60       | 150    |
| 10 | 75       | 150    |
| .. | ...      | ...    |
+----+----------+--------+
Run Code Online (Sandbox Code Playgroud)

结果集是一个扁平的线性空闲报告,但由于这些重叠太多,我最终会使用负时间.即如果上面的窗口ID = 10是150秒长,并且我总结了从窗口大小中减去的相对秒的差异,我会结束150-(20+20+90+75)=-55.我尝试过这种方法,这也是让我意识到需要平整的重叠的原因.

所以,我正在寻找的解决方案是将重叠压缩成一组:

+----+----------+--------+
| ID | TimeFrom | TimeTo |
+----+----------+--------+
| 10 | 10       | 30     |
| 10 | 50       | 150    |
| .. | ...      | ...    |
+----+----------+--------+
Run Code Online (Sandbox Code Playgroud)

注意事项:性能在这里非常重要,因为这是一个更大的查询的一部分,它将自己表现良好,如果我能帮助它,我宁愿不影响它的性能.

关于"哪个秒有间隔"的评论,这是我为最终结果尝试的东西,我正在寻找具有更好性能的东西.适应我的例子:

SELECT SUM(C.N)
FROM (
    SELECT A.N, ROW_NUMBER()OVER(ORDER BY A.N) RowID
    FROM 
          (SELECT TOP 60 1 N FROM master..spt_values) A
        , (SELECT TOP 720 1 N FROM master..spt_values) B
    ) C
WHERE EXISTS (
        SELECT 1
        FROM Times SE
        WHERE SE.ID = 10
            AND SE.TimeFrom <= C.RowID
            AND SE.TimeTo >= C.RowID
            AND EXISTS (
                SELECT 1
                FROM Times2 D
                WHERE ID = SE.ID
                    AND D.TimeFrom <= C.RowID
                    AND D.TimeTo >= C.RowID
            )
        GROUP BY SE.ID
    )
Run Code Online (Sandbox Code Playgroud)

我在这个解决方案中遇到的问题是我在查询计划中的EXISTS查询中得到一个Row Count Spool,执行次数等于COUNT(C.*).我在该查询中留下了实数,以说明绕过这种方法是最好的.因为即使使用Row Count Spool也会大大降低查询成本,因此执行计数也会大大增加查询的成本.

进一步编辑:最终目标是将其放在一个过程中,因此表变量和临时表也是一种可能使用的工具.

Pie*_*ens 1

将每一行左连接到具有相同 ID 值(如果存在)的后继重叠行。

现在,对于结果集中的每一行,LHS left join RHSID 对经过时间的贡献是:

isnull(RHS.TimeFrom,LHS.TimeTo) - LHS.TimeFrom as TimeElapsed

通过 ID 对这些进行求和应该会给出正确的答案。

请注意:
- 如果没有重叠的后继行,则计算很简单
LHS.TimeTo - LHS.TimeFrom
- 如果有重叠的后继行,则计算将简化
(RHS.TimeFrom - LHS.TimeFrom) + (RHS.TimeTo - RHS.TimeFrom)

RHS.TimeTo - LHS.TimeFrom