Goede oplossing
SELECT *
FROM (
SELECT day::date
FROM generate_series(timestamp '2007-12-01'
, timestamp '2008-12-01'
, interval '1 month') day
) d
LEFT JOIN (
SELECT date_trunc('month', date_col)::date AS day
, count(*) AS some_count
FROM tbl
WHERE date_col >= date '2007-12-01'
AND date_col <= date '2008-12-06'
-- AND ... more conditions
GROUP BY 1
) t USING (day)
ORDER BY day;
-
Gebruik
LEFT JOIN
, natuurlijk. -
generate_series()
kan on-the-fly en zeer snel een tabel met tijdstempels produceren. -
Het is over het algemeen sneller om vóór . te verzamelen jij doet mee. Ik heb onlangs een testcase gegeven op sqlfiddle.com in dit gerelateerde antwoord:
- PostgreSQL - rangschikken op array
-
Cast de
timestamp
totdate
(::date
) voor een basisformaat. Gebruik voor meerto_char()
. -
GROUP BY 1
is een syntaxisafkorting om te verwijzen naar de eerste uitvoerkolom. KanGROUP BY day
zijn ook, maar dat kan in strijd zijn met een bestaande kolom met dezelfde naam. OfGROUP BY date_trunc('month', date_col)::date
maar dat is te lang naar mijn smaak. -
Werkt met de beschikbare intervalargumenten voor
date_trunc()
. -
count()
produceert nooitNULL
(0
voor geen rijen), maar deLEFT JOIN
doet.
Te retourneren0
in plaats vanNULL
in de buitensteSELECT
, gebruikCOALESCE(some_count, 0) AS some_count
. De handleiding. -
Voor een meer algemene oplossing of willekeurige tijdsintervallen overweeg dit nauw verwante antwoord:
- De beste manier om records te tellen met willekeurige tijdsintervallen in Rails+Postgres