Ho una tabella (in PostgreSQL 9.4) che assomiglia a questa:
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');
Ora voglio calcolare per le date date e per ogni tipo, in quante righe dates_ranges
cadono da ciascuna data. Gli zeri potrebbero essere eventualmente omessi.
Risultato desiderato:
+-------+------------+----+
| 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 |
+-------+------------+----+
Ho escogitato due soluzioni, una con LEFT JOIN
eGROUP 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
e uno con LATERAL
, che è leggermente più veloce:
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
Mi chiedo: è un modo migliore per scrivere questa query? E come includere coppie tipo-data con 0 conteggi?
In realtà ci sono alcuni tipi distinti, periodo fino a cinque anni (1800 date) e ~ 30k righe nella dates_ranges
tabella (ma potrebbe crescere in modo significativo).
Non ci sono indici Per essere precisi nel mio caso è il risultato di una query secondaria, ma ho voluto limitare la domanda a un problema, quindi è più generale.
2018-01-31
o 2018-01-30
o 2018-01-29
quando ci sono tutti nella prima gamma?
generate_series
sono parametri esterni - non necessariamente coprono tutti gli intervalli nella dates_ranges
tabella. Per quanto riguarda la prima domanda, suppongo di non capirlo: le righe dates_ranges
sono indipendenti, non voglio determinare la sovrapposizione.
(1,2018-01-01,2018-01-15)
e(1,2018-01-20,2018-01-25)
vuoi tenerne conto nel determinare quante date sovrapposte hai?