【发布时间】:2010-11-01 03:31:17
【问题描述】:
我有大量数据,其中包含给定 ID 的开始和停止时间,我需要将所有相交和相邻的时间跨度展平为一个组合时间跨度。下面贴出的样例数据都是同一个ID,所以我就不一一列举了。
为了让事情更清楚一点,请查看 03.06.2009 的示例数据:
以下时间跨度重叠或连续,需要合并为一个时间跨度
- 05:54:48 - 10:00:13
- 09:26:45 - 09:59:40
生成的时间跨度将从 05:54:48 到 10:00:13。由于 10:00:13 和 10:12:50 之间存在间隔,因此我们还有以下时间跨度:
- 10:12:50 - 10:27:25
- 10:13:12 - 11:14:56
- 10:27:25 - 10:27:31
- 10:27:39 - 13:53:38
- 11:14:56 - 11:15:03
- 11:15:30 - 14:02:14
- 13:53:38 - 13:53:43
- 14:02:14 - 14:02:31
这导致从 10:12:50 到 14:02:31 的一个合并时间跨度,因为它们重叠或相邻。
您将在下面找到我需要的示例数据和展平数据。持续时间列只是提供信息。
任何解决方案(无论是否 SQL)都值得赞赏。
编辑:由于有许多不同且有趣的解决方案,我正在通过添加约束来完善我的原始问题,以查看“最佳”(如果有的话)解决方案冒泡:
- 我正在通过 ODBC 从另一个系统获取数据。无法为我更改表格布局或添加索引
- 数据仅按日期列索引(时间部分不是)
- 每天大约有 2.5k 行
- 估计的数据使用模式大致如下:
- 大多数情况下(比如说 90%)用户只会查询一两天(2.5k - 5k 行)
- 有时 (9%) 范围最长为一个月(~75k 行)
- 很少 (1%) 范围会长达一年(约 90 万行)
- 对于典型情况,查询应该很快,而对于罕见情况,查询不应“永远持续”。
- 查询一年的数据大约需要 5 分钟(无连接的普通选择)
在这些限制条件下,最佳解决方案是什么?恐怕大多数解决方案都会非常慢,因为它们加入日期和时间的组合,在我的情况下这不是索引字段。
您会在客户端还是服务器端进行所有合并?您会首先创建一个优化的临时表并使用该表的建议解决方案之一吗?直到现在我都没有时间测试解决方案,但我会随时通知您最适合我的解决方案。
样本数据:
Date | Start | Stop
-----------+----------+---------
02.06.2009 | 05:55:28 | 09:58:27
02.06.2009 | 10:15:19 | 13:58:24
02.06.2009 | 13:58:24 | 13:58:43
03.06.2009 | 05:54:48 | 10:00:13
03.06.2009 | 09:26:45 | 09:59:40
03.06.2009 | 10:12:50 | 10:27:25
03.06.2009 | 10:13:12 | 11:14:56
03.06.2009 | 10:27:25 | 10:27:31
03.06.2009 | 10:27:39 | 13:53:38
03.06.2009 | 11:14:56 | 11:15:03
03.06.2009 | 11:15:30 | 14:02:14
03.06.2009 | 13:53:38 | 13:53:43
03.06.2009 | 14:02:14 | 14:02:31
04.06.2009 | 05:48:27 | 09:58:59
04.06.2009 | 06:00:00 | 09:59:07
04.06.2009 | 10:15:52 | 13:54:52
04.06.2009 | 10:16:01 | 13:24:20
04.06.2009 | 13:24:20 | 13:24:24
04.06.2009 | 13:24:32 | 14:00:39
04.06.2009 | 13:54:52 | 13:54:58
04.06.2009 | 14:00:39 | 14:00:49
05.06.2009 | 05:53:58 | 09:59:12
05.06.2009 | 10:16:05 | 13:59:08
05.06.2009 | 13:59:08 | 13:59:16
06.06.2009 | 06:04:00 | 10:00:00
06.06.2009 | 10:16:54 | 10:18:40
06.06.2009 | 10:18:40 | 10:18:45
06.06.2009 | 10:23:00 | 13:57:00
06.06.2009 | 10:23:48 | 13:57:54
06.06.2009 | 13:57:21 | 13:57:38
06.06.2009 | 13:57:54 | 13:57:58
07.06.2009 | 21:59:30 | 01:58:49
07.06.2009 | 22:12:16 | 01:58:39
07.06.2009 | 22:12:25 | 01:58:28
08.06.2009 | 02:10:33 | 05:56:11
08.06.2009 | 02:10:43 | 05:56:23
08.06.2009 | 02:10:49 | 05:55:59
08.06.2009 | 05:55:59 | 05:56:01
08.06.2009 | 05:56:11 | 05:56:14
08.06.2009 | 05:56:23 | 05:56:27
扁平化结果:
Date | Start | Stop | Duration
-----------+----------+----------+---------
02.06.2009 | 05:55:28 | 09:58:27 | 04:02:59
02.06.2009 | 10:15:19 | 13:58:43 | 03:43:24
03.06.2009 | 05:54:48 | 10:00:13 | 04:05:25
03.06.2009 | 10:12:50 | 14:02:31 | 03:49:41
04.06.2009 | 05:48:27 | 09:59:07 | 04:10:40
04.06.2009 | 10:15:52 | 14:00:49 | 03:44:58
05.06.2009 | 05:53:58 | 09:59:12 | 04:05:14
05.06.2009 | 10:16:05 | 13:59:16 | 03:43:11
06.06.2009 | 06:04:00 | 10:00:00 | 03:56:00
06.06.2009 | 10:16:54 | 10:18:45 | 00:01:51
06.06.2009 | 10:23:00 | 13:57:58 | 03:34:58
07.06.2009 | 21:59:30 | 01:58:49 | 03:59:19
08.06.2009 | 02:10:33 | 05:56:27 | 03:45:54
【问题讨论】:
-
您能否判断开始和停止时间之间是否超过 24 小时?或者这不是您的数据集的问题?
-
@Ed:时间跨度大多在一个班次内,即从06:00到14:00、14:00到22:00和22:00到06:00。正如您所看到的,通常早一点开始(例如 5:55)然后晚一点结束。
-
一方面你写“每天大约有 2.5k 行”,另一方面“时间跨度大多在一个班次内”8 小时。那么,您希望加入的这些时间间隔通常是多长时间?
-
@Matt:我的意思是相交和相邻的时间跨度会导致合并的时间跨度通常在一个班次内。
-
回答 Ed 最初的问题:不,不会有一个大于 24 小时的开始和停止时间。
标签: sql sql-server sql-server-2005 algorithm datetime