Postgresql generate_series динамический интервал

Привет, я хочу сделать динамические временные ряды, используя generate_series в Postgresql.

Например, у меня есть набор случайных дат:

cleaning date
2015-03-01 00:00
2015-05-31 00:00
2015-06-13 00:00

и я хочу динамически разделить период даты на эти даты очистки.

Результат будет таким:

start date         end date
0000-00-00 00:00   2015-03-01 00:00
2015-03-01 00:00   2015-05-31 00:00
2015-05-31 00:00   2015-06-13 00:00
2015-06-13 00:00   (current_timestamp)

Я понятия не имею, как установить динамический интервал в generate_series... Возможно ли это для generate_series?


person user3432269    schedule 30.03.2016    source источник
comment
0000-00-00 00:00 недопустимая дата   -  person a_horse_with_no_name    schedule 30.03.2016


Ответы (1)


Я действительно не вижу смысла использовать generate_series.

Чтобы получить результат, который вы предложили, вы можете использовать ROW_NUMBER и самосоединение:

CREATE TABLE tab(cleaning timestamp);

INSERT INTO tab(cleaning)
VALUES ('2015-03-01 00:00'), ('2015-05-31 00:00'), ('2015-06-13 00:00');

Основной запрос:

WITH cte AS
(
   SELECT cleaning, ROW_NUMBER() OVER(ORDER BY cleaning) AS rn
   FROM tab
)
SELECT COALESCE(c1.cleaning,'0001-01-01'::timestamp) AS start_date,
       COALESCE(c2.cleaning,CURRENT_TIMESTAMP) AS end_date
FROM cte c1
FULL JOIN cte c2
  ON c1.rn = c2.rn-1
ORDER BY start_date;

SqlFiddleDemo

Вывод:

╔═══════════════════════════╦═════════════════════════╗
║        start_date         ║        end_date         ║
╠═══════════════════════════╬═════════════════════════╣
║ January, 01 0001 00:00:00 ║ March, 01 2015 00:00:00 ║
║ March,   01 2015 00:00:00 ║ May,   31 2015 00:00:00 ║
║ May,     31 2015 00:00:00 ║ June,  13 2015 00:00:00 ║
║ June,    13 2015 00:00:00 ║ March, 30 2016 11:03:38 ║
╚═══════════════════════════╩═════════════════════════╝

ИЗМЕНИТЬ:

Другая возможность — использовать LAG/LEAD оконных функций:

SELECT COALESCE(LAG(cleaning) OVER(ORDER BY cleaning), '0001-01-01'::timestamp) 
       AS start_date
      ,cleaning AS end_date
FROM tab
UNION ALL
SELECT MAX(cleaning), CURRENT_TIMESTAMP
FROM tab
ORDER BY start_date;

SqlFiddleDemo2

person Lukasz Szozda    schedule 30.03.2016