Разделение временной метки на две строки в postgresql
У меня есть две метки времени в таблице:
usage_from | usage_till
---------------------+--------------------
2013-10-09 23:08:17 | 2013-10-09 23:16:00
2013-10-09 23:08:17 | 2013-10-09 23:08:19
2013-10-09 23:08:17 | 2013-10-10 18:58:22
2013-10-09 23:08:17 | 2013-10-09 23:15:05
2013-10-09 23:08:17 | 2013-10-09 23:09:00
2013-10-09 23:08:17 | 2013-10-09 23:08:20
2013-10-09 23:08:17 | 2013-10-09 23:32:04
2013-10-09 23:08:17 | 2013-10-10 02:02:03
2013-10-09 23:08:17 | 2013-10-10 07:31:00
2013-10-09 23:08:17 | 2013-10-10 22:41:04
Это мне нужно разделить, как показано ниже:
usage_from | usage_till
---------------------+-----------------------
2013-10-09 23:08:17 | 2013-10-09 23:16:00
2013-10-09 23:08:17 | 2013-10-09 23:08:19
2013-10-09 23:08:17 | 2013-10-10 02:00:00
2013-10-10 02:00:00 | 2013-10-10 18:58:22 -- splitted
2013-10-09 23:08:17 | 2013-10-09 23:15:05
2013-10-09 23:08:17 | 2013-10-09 23:09:00
2013-10-09 23:08:17 | 2013-10-09 23:08:20
2013-10-09 23:08:17 | 2013-10-09 23:32:04
2013-10-09 23:08:17 | 2013-10-10 02:00:00
2013-10-10 02:00:00 | 2013-10-10 02:02:03 -- splitted
2013-10-09 23:08:17 | 2013-10-10 02:00:00
2013-10-10 02:00:00 | 2013-10-10 07:31:00 -- splitted
2013-10-09 23:08:17 | 2013-10-10 02:00:00
2013-10-10 02:00:00 | 2013-10-10 22:41:04 -- splitted
Здесь, в приведенном выше примере, я разделил отметку времени в 02:00:00.
После многих испытаний я мог разделить его, как показано ниже, но не смог разделить как другой ряд.
usage_from | usage_till | end_time_1 | end_time_2
---------------------+---------------------+---------------------+---------------------
2013-10-09 23:08:17 | 2013-10-09 23:16:00 | 2013-10-09 23:16:00 | 2013-10-11 02:00:00
2013-10-09 23:08:17 | 2013-10-09 23:08:19 | 2013-10-09 23:08:19 | 2013-10-11 02:00:00
2013-10-09 23:08:17 | 2013-10-10 18:58:22 | 2013-10-10 02:00:00 | 2013-10-10 18:58:22
2013-10-09 23:08:17 | 2013-10-09 23:15:05 | 2013-10-09 23:15:05 | 2013-10-11 02:00:00
2013-10-09 23:08:17 | 2013-10-09 23:09:00 | 2013-10-09 23:09:00 | 2013-10-11 02:00:00
2013-10-09 23:08:17 | 2013-10-09 23:08:20 | 2013-10-09 23:08:20 | 2013-10-11 02:00:00
2013-10-09 23:08:17 | 2013-10-09 23:32:04 | 2013-10-09 23:32:04 | 2013-10-11 02:00:00
2013-10-09 23:08:17 | 2013-10-10 02:02:03 | 2013-10-10 02:00:00 | 2013-10-10 02:02:03
2013-10-09 23:08:17 | 2013-10-10 07:31:00 | 2013-10-10 02:00:00 | 2013-10-10 07:31:00
2013-10-09 23:08:17 | 2013-10-10 22:41:04 | 2013-10-10 02:00:00 | 2013-10-10 22:41:04
есть идеи как это сделать? Я боролся в течение последних нескольких дней.
Я использую Redshift 1.0.757 (на основе PostgreSQL 8.02).
1 ответ
Если 1 Redshift будет поддерживать базовую форму generate_series()
, это может сработать. По крайней мере, это работает в Postgres 8.3:
SELECT CASE WHEN split > 0 AND g = 0 THEN usage_from
WHEN split > 0 AND g = 1 THEN usage_till::date + '2:0'::time
ELSE usage_from END
, CASE WHEN split > 0 AND g = 0 THEN usage_till::date + '2:0'::time
WHEN split > 0 AND g = 1 THEN usage_till
ELSE usage_till END
FROM (
SELECT * , generate_series(0, split) AS g
FROM (
SELECT *
, (usage_till - '2:0'::time)::date
- (usage_from - '2:0'::time)::date AS split -- results in integer
FROM t
) sub1
) sub2
Как?
Во внутреннем подзапросе
sub1
Я нахожу, пересекает ли временной интервал 2 часа ночи, и сохраняю это в столбцеsplit
, Я предполагаю, что временной интервал никогда не пересекает два часа ночи дважды, но запрос можно легко адаптировать к этому.generate_series()
автоматически генерирует 1 строку за обтекание.В следующем подзапросе
sub2
generate_series()
генерирует две строки, где требуется разделение.Во внешнем операторе SELECT оператор CASE соответствующим образом корректирует временные метки.
Обычно я бы использовал
interval '2 hours'
вместо'2:0'::time
, но я помню, что Redshift не поддерживаетinterval
тип.
Не в Redshift?
Если Redshift позволяет только generate_series()
в FROM
список, а не в SELECT
список, вам не повезло. Это уже древняя форма. В современном Postgres вы бы использовали LATERAL JOIN
, Вы можете попытать счастья с помощью regexp_split_to_table (), но этого также нет в Postgres 8.0.
1 Но в руководстве сказано: generate_series()
не поддерживается.
За исключением этого, я могу думать только о процедурном решении с PL/pgSQL. Но Redshift тоже может быть ограничен...