我有 4 个不同的时间段,
a
、b
、c
和 d
。
a
与 b
b
与 c
a
和 c
不重叠d
不与 a
、b
或 c
但是,我希望能够将这些全部链接到一个时间段中,无论有多少个不同的时间段可能链接在一起。另一个挑战是我有其他不重叠的时间段,所以我不能简单地对所有数据进行
MIN()
和MAX()
。
以下是我目前的尝试
DROP TABLE IF EXISTS #test
CREATE TABLE
#test (id VARCHAR, start_time DATETIME2, end_time DATETIME2)
INSERT INTO
#test
VALUES
('a', '2024-08-03 12:35:37', '2024-08-07 12:36:42'),
('b', '2024-08-06 18:35:53', '2024-08-10 13:12:50'),
('c', '2024-08-09 12:40:13', '2024-08-11 00:00:00'),
('d', '2024-01-09 12:40:13', '2024-02-11 00:00:00');
WITH overlaps AS (
SELECT
a.id,
a.start_time AS orig_start,
a.end_time AS orig_end,
LEAST(a.start_time, b.start_time) AS overlap_start,
GREATEST(a.end_time, b.end_time) AS overlap_end
FROM
#test AS a
LEFT JOIN
#test AS b
ON b.id != a.id -- Don't overlap with self
AND GREATEST(a.start_time, b.start_time) < LEAST(a.end_time, b.end_time) -- catch any overlap time periods
),
merged AS (
SELECT
a.id,
a.orig_start,
a.orig_end,
MIN(overlap_start) AS merged_start,
MAX(overlap_end) AS merged_end
FROM
overlaps AS a
GROUP BY
a.id,
a.orig_start,
a.orig_end
)
SELECT DISTINCT
id,
merged_start,
merged_end
FROM
merged
ORDER BY
merged_start;
期望的最终目标将是这样的表格:
DROP TABLE IF EXISTS #desired
CREATE TABLE
#desired (rn INT, start_time DATETIME2, end_time DATETIME2)
INSERT INTO
#desired
VALUES
(1, '2024-01-09 12:40:13', '2024-02-11 00:00:00'),
(2, '2024-08-03 12:35:37', '2024-08-11 00:00:00');
SELECT
*
FROM
#desired;
这是一种方法,它与您的尝试没有什么不同,只是最后一步必须停止按
id
分组:
WITH AllPossibleOverlaps AS
(
SELECT t1.id,
s = MIN(t2.start_time),
e = MAX(t2.end_time)
FROM #test AS t1
INNER JOIN #test AS t2
ON t2.end_time >= t1.start_time
AND t2.start_time <= t1.end_time
GROUP BY t1.id
),
OverlapsById AS
(
SELECT x.id,
start_time = MIN(x2.s),
end_time = MAX(x2.e)
FROM AllPossibleOverlaps AS x
INNER JOIN AllPossibleOverlaps AS x2
ON x.e >= x2.s
AND x.s <= x2.e
GROUP BY x.id
)
SELECT rn = ROW_NUMBER() OVER (ORDER BY start_time),
start_time,
end_time
FROM OverlapsById
GROUP BY start_time,
end_time
ORDER BY rn;