У меня много данных с указанием времени начала и окончания для данного идентификатора, и мне нужно объединить все пересекающиеся и смежные временные области в один объединенный временной интервал. Все приведенные ниже примеры данных приведены для одного и того же идентификатора, поэтому я не перечислил их.
Чтобы прояснить ситуацию, взгляните на пример данных за 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,5 тыс. Строк
- Примерная схема использования данных примерно следующая:
- Большую часть времени (скажем, 90%) пользователь будет запрашивать только один или два дня (строки от 2,5 до 5 тысяч)
- Иногда (9%) диапазон может составлять до месяца (~ 75 тыс. Строк)
- Редко (1%) диапазон будет до года (~ 900 тыс. Строк)
- Запрос должен быть быстрым для типичного случая, а не "вечным" для редкого случая.
- Запрос данных за год занимает около 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