У мене є таблиця (в PostgreSQL 9.4), яка виглядає приблизно так:
CREATE TABLE dates_ranges (kind int, start_date date, end_date date);
INSERT INTO dates_ranges VALUES
(1, '2018-01-01', '2018-01-31'),
(1, '2018-01-01', '2018-01-05'),
(1, '2018-01-03', '2018-01-06'),
(2, '2018-01-01', '2018-01-01'),
(2, '2018-01-01', '2018-01-02'),
(3, '2018-01-02', '2018-01-08'),
(3, '2018-01-05', '2018-01-10');
Тепер я хочу обчислити для вказаних дат і для кожного виду, у скільки рядків від dates_ranges
кожної дати. Нулі можуть бути опущені.
Бажаний результат:
+-------+------------+----+
| kind | as_of_date | n |
+-------+------------+----+
| 1 | 2018-01-01 | 2 |
| 1 | 2018-01-02 | 2 |
| 1 | 2018-01-03 | 3 |
| 2 | 2018-01-01 | 2 |
| 2 | 2018-01-02 | 1 |
| 3 | 2018-01-02 | 1 |
| 3 | 2018-01-03 | 1 |
+-------+------------+----+
Я придумав два рішення: одне з LEFT JOIN
іGROUP BY
SELECT
kind, as_of_date, COUNT(*) n
FROM
(SELECT d::date AS as_of_date FROM generate_series('2018-01-01'::timestamp, '2018-01-03'::timestamp, '1 day') d) dates
LEFT JOIN
dates_ranges ON dates.as_of_date BETWEEN start_date AND end_date
GROUP BY 1,2 ORDER BY 1,2
і один з LATERAL
, який трохи швидше:
SELECT
kind, as_of_date, n
FROM
(SELECT d::date AS as_of_date FROM generate_series('2018-01-01'::timestamp, '2018-01-03'::timestamp, '1 day') d) dates,
LATERAL
(SELECT kind, COUNT(*) AS n FROM dates_ranges WHERE dates.as_of_date BETWEEN start_date AND end_date GROUP BY kind) ss
ORDER BY kind, as_of_date
Мені цікаво, чи є кращий спосіб написати цей запит? І як включити пари-дату з числом 0?
Насправді існує кілька різних видів, період до п'яти років (1800 дат) і ~ 30 к рядків у dates_ranges
таблиці (але він може значно зрости).
Індекси немає. Якщо бути точним, в моєму випадку це результат підзапиту, але я хотів обмежити питання однією проблемою, тому це більш загальне.
2018-01-31
чи 2018-01-30
або 2018-01-29
в ній , коли перший діапазон має всі з них?
generate_series
це зовнішні параметри - вони не обов'язково охоплюють усі діапазони dates_ranges
таблиці. Щодо першого питання, я вважаю, що я його не розумію - рядки в dates_ranges
незалежних, я не хочу визначати збіги.
(1,2018-01-01,2018-01-15)
і(1,2018-01-20,2018-01-25)
ви хочете це врахувати, визначаючи, скільки дат перекриття у вас є?