我有下EventTimes
表:
DROP TABLE IF EXISTS dbo.EventTimes;
CREATE TABLE dbo.EventTimes
(
EventTimeKeyId INT IDENTITY(1,1) PRIMARY KEY,
EventId INT NOT NULL,
StartTime TIME NOT NULL,
EndTime TIME NOT NULL
);
具有以下数据:
-- Event 1
INSERT INTO dbo.EventTimes (EventId, StartTime, EndTime)
VALUES
(1, '04:00:00', '14:00:00'),
(1, '06:00:00', '11:00:00'),
(1, '09:00:00', '12:00:00'),
(1, '13:00:00', '14:00:00'), -- Gap between this row and the next row
(1, '02:30:00', '04:00:00'); -- Notice the half-hour on this one
-- Event 2
INSERT INTO dbo.EventTimes (EventId, StartTime, EndTime)
VALUES
(2, '00:00:00', '06:00:00'), -- Gap between this row and the next row
(2, '09:00:00', '13:00:00'),
(2, '11:00:00', '15:00:00');
注意:
- 同一
Event
时间范围可以有两个相互重叠的时间范围。例如,Event
从凌晨 4 点到下午 2 点以及早上 6 点到上午 11 点也是如此。 - 两个时间范围之间也可能存在间隙。例如
Event
,下午 1 点至 2 点以及下午 2:30 至 4 点也是如此。
最终目标:
我正在尝试计算给TotalTime
定的Event
忽略重复的重叠时间。例如,对于上午 9 点到下午 1 点和上午 11 点到下午 3 点的范围集,不同的TotalTime
时间应该是 6 小时(上午 9 点到下午 3 点)。相反,我也不想计算两个时间范围之间的间隙时间。因此,对于下午 1 点到 2 点以及下午 2:30 到 4 点的范围集,TotalTime
应该是 2.5 小时。(请注意,这些只是上面完整示例的子集,最终结果应该是每个 的所有这些唯一时间的总和Event
。)
不应TotalTime
超过 24 小时,这些时间都在一天之内(TIME
数据类型也是如此)。
上面脚本中提供的示例的预期最终结果:
其他信息:
如果使用日期时间更容易,请随意将数据类型从 更改
TIME
为DATETIME
。我可以将结果转换回来,没问题。我相信需要某种递归来解决这个问题。我觉得我已经非常接近解决方案,但还没有完全实现。
在 2:30 - 4:00 和 4:00 - 14:00 等情况下,我预计总时间为 11.5 小时。
所有的复杂性都是由重叠的间隔造成的。
如果我们打包间隔以使其不存在重叠,则解决方案就是简单的分组和求和。
以下代码使用 Itzik Ben-Gan 的间隔打包解决方案:
使用 上的索引可以避免初始排序
(EventId, StartTime, EndTime)
。这是一个使用运行长度编码来压缩重叠时间范围的解决方案 -
模式和期望的输出
解决方案
DB Fiddle 供参考