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也会大大降低查询成本,因此执行计数也会大大增加查询的成本.
进一步编辑:最终目标是将其放在一个过程中,因此表变量和临时表也是一种可能使用的工具.
将每一行左连接到具有相同 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