我的DB表有两列有趣的内容,第一列是给定物理区域内许多事件的开始(或开启)时间,第二列是结束(或关闭)时间。
要求是确定车辆在该区域内的唯一时间段。因此,第一个事件的开始到最后一个事件的结束是一个连续的时间段。生成的表不需要该时间段内的开或关事件数。
有数百万行,因此由于结果表的大小,联接可能会导致问题。我不反对,但是...
数据:
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 Server,因此T-SQL或ANSI是理想的选择,但我已经准备好进行一些翻译了。
(为澄清起见,我正在尝试将timeOn到timeOff的重叠时间序列合并为每个连续序列的一行)
答案 0 :(得分:3)
这是合并重叠间隔的经典问题。最简单的解决方案是按起点和组行对数据进行排序,每当发现最大值与最大值之间的间隔时,就开始新的组。终点位于上一行的起点和当前行的起点。
以下解决方案基于此想法(我使用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