Мне нужно работать с этой periods
таблицей:
периодов
id | starts_on | ends_on
----+------------+------------
678 | 2019-12-21 | 2019-12-22
534 | 2019-12-23 | 2020-01-04
679 | 2019-12-28 | 2019-12-29
9 | 2020-01-01 | 2020-01-01
776 | 2020-01-04 | 2020-01-05
7 | 2020-01-06 | 2020-01-06
777 | 2020-01-11 | 2020-01-12
В нем перечислены все периоды, когда студентам не нужно go в школу. К сожалению, некоторые периоды перекрываются. Это происходит, когда во время школьных каникул выходной или праздничный c выходной (у каждого из них есть свои собственные строки периодов).
С помощью Найти строки с диапазонами дат закрытия и накапливать их продолжительности и Пробелы и острова для школьных каникул в стране с федеральными землями Я закончил с этим запросом:
SELECT p.id, p.starts_on, p.ends_on, grp,
(Max(ends_on) OVER (PARTITION BY grp) - Min(starts_on) OVER (PARTITION BY grp)
) + 1 AS duration, Array_agg(p.id) OVER (PARTITION BY grp)
FROM (SELECT p.*,
Count(*) FILTER (WHERE prev_eo < starts_on - INTERVAL '1 day') OVER
(PARTITION BY 1
ORDER BY starts_on
) AS grp
FROM (SELECT p.*,
lag(ends_on) OVER (PARTITION BY 1 ORDER BY starts_on) AS prev_eo
FROM (SELECT p.id, p.starts_on, p.ends_on FROM periods p
WHERE starts_on > '2019-12-15' AND
starts_on < '2020-01-15' ) p
) p
) p;
Что я получу
Это приводит в
id | starts_on | ends_on | grp | duration | array_agg
----+------------+------------+-----+----------+---------------
678 | 2019-12-21 | 2019-12-22 | 0 | 15 | {678,534,679}
534 | 2019-12-23 | 2020-01-04 | 0 | 15 | {678,534,679}
679 | 2019-12-28 | 2019-12-29 | 0 | 15 | {678,534,679}
9 | 2020-01-01 | 2020-01-01 | 1 | 1 | {9}
776 | 2020-01-04 | 2020-01-05 | 2 | 3 | {776,7}
7 | 2020-01-06 | 2020-01-06 | 2 | 3 | {776,7}
777 | 2020-01-11 | 2020-01-12 | 3 | 2 | {777}
Первые три строки: grp
0 (идентификаторы 678, 534 и 679).
Что я хочу
Но идентификаторы 9, 776 и 7 тоже должны принадлежать этому grp
. К сожалению, они перекрываются. Можно ли получить результат, который как-то так (мне безразличен порядок)?
id | starts_on | ends_on | grp | duration | array_agg
----+------------+------------+-----+----------+---------------
678 | 2019-12-21 | 2019-12-22 | 0 | 17 | {678,534,679,9,776,7}
534 | 2019-12-23 | 2020-01-04 | 0 | 17 | {678,534,679,9,776,7}
679 | 2019-12-28 | 2019-12-29 | 0 | 17 | {678,534,679,9,776,7}
9 | 2020-01-01 | 2020-01-01 | 0 | 17 | {678,534,679,9,776,7}
776 | 2020-01-04 | 2020-01-05 | 0 | 17 | {678,534,679,9,776,7}
7 | 2020-01-06 | 2020-01-06 | 0 | 17 | {678,534,679,9,776,7}
777 | 2020-01-11 | 2020-01-12 | 1 | 2 | {777}
Я хочу знать, как долго длится весь остров (группа 0) и какие идентификаторы периода, которые он содержит.
Песочница: https://rextester.com/SHVL41709