合并存储为开始时间和结束时间的重叠时间段

Consolidate overlapping time periods stored as start and end time

我的数据库 table 有两列感兴趣,第一列是给定物理区域内许多事件的开始(或开启)时间,第二列是结束(或关闭)时间。

要求确定车辆在该区域内的唯一时间段。所以第一个事件的开始到最后一个事件的结束是一个连续的时期。结果 table.

不需要期间内的 on 或 off 事件数

有数百万行,因此由于结果 table 的大小,连接可能会导致问题。我不反对,但是...

数据:

id          timeOn                    timeOff
761058840   2018-01-02 07:54:28.000   2018-01-02 08:33:34.000
761058840   2018-01-02 07:54:28.000   2018-01-02 08:36:30.000
761058840   2018-01-02 08:33:45.000   2018-01-02 08:35:30.000
761058840   2018-01-02 13:11:18.000   2018-01-02 13:14:04.000
761058840   2018-01-02 13:11:18.000   2018-01-02 13:39:40.000
761058840   2018-01-02 13:22:11.000   2018-01-02 13:40:25.000
761058840   2018-01-02 15:56:18.000   2018-01-02 15:59:34.000
761058840   2018-01-02 15:56:18.000   2018-01-02 16:36:25.000
761058840   2018-01-02 16:01:34.000   2018-01-02 16:05:34.000
761058840   2018-01-02 16:33:19.000   2018-01-02 16:38:26.000
761058840   2018-01-02 21:20:25.000   2018-01-02 21:24:25.000
761058840   2018-01-02 22:20:36.000   2018-01-03 05:20:37.000
761058840   2018-01-02 22:20:36.000   2018-01-03 05:20:37.000
761058840   2018-01-03 08:31:29.000   2018-01-03 09:01:10.000
761058840   2018-01-03 08:31:59.000   2018-01-03 09:01:07.000
761058840   2018-01-03 09:01:57.000   2018-01-03 09:06:27.000
761058840   2018-01-03 14:07:27.000   2018-01-03 14:17:32.000
761058840   2018-01-03 14:09:28.000   2018-01-03 14:45:00.000
761058840   2018-01-03 14:19:32.000   2018-01-03 14:48:22.000
761058840   2018-01-03 17:30:38.000   2018-01-03 18:06:35.000
761058840   2018-01-03 17:33:54.000   2018-01-03 18:09:48.000

考虑此数据中的行,我要查找的是:

761058840   2018-01-02 07:54:28.000   2018-01-02 08:36:30.000
761058840   2018-01-02 13:11:18.000   2018-01-02 13:40:25.000
761058840   2018-01-02 15:56:18.000   2018-01-02 16:38:26.000
761058840   2018-01-02 21:20:25.000   2018-01-02 21:24:25.000
761058840   2018-01-02 22:20:36.000   2018-01-03 05:20:37.000
761058840   2018-01-03 08:31:59.000   2018-01-03 09:01:07.000
761058840   2018-01-03 09:01:57.000   2018-01-03 09:06:27.000
761058840   2018-01-03 14:07:27.000   2018-01-03 14:48:22.000
761058840   2018-01-03 17:30:38.000   2018-01-03 18:09:48.000

其他解决方案是针对日期的,我在一个小时内有多个事件。其他解决方案将事件分类为时间段(按小时分类)。

好像没有连续时间的东西

数据库是 SQL 服务器,因此 T-SQL 或 ANSI 是理想的,但我准备进行一些翻译。

(编辑澄清:我正在尝试将重叠时间序列从 timeOn 到 timeOff 合并为每个连续序列的一行)

这是合并重叠区间的经典问题。最简单的解决方案是按起点和组行对数据进行排序,每次发现最大值之间的差距时开始新组。前几行的终点和当前行的起点。

下面的解决方案就是基于这个思路(我用的是ROWS BETWEEN ...而不是LAG):

WITH t_with_change AS (
    SELECT id, timeOn, timeOff, CASE WHEN MAX(timeOff) OVER (PARTITION BY ID ORDER BY timeOn ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) >= timeOn THEN 0 ELSE 1 END AS chg
    FROM @t
), t_with_groups AS(
    SELECT id, timeOn, timeOff, SUM(chg) OVER (PARTITION BY ID ORDER BY timeOn) AS grp
    FROM t_with_change
)
SELECT id, grp, MIN(timeOn) AS timeOn, MAX(timeOff) AS timeOff
FROM t_with_groups
GROUP BY id, grp

DB Fiddle