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
timestamptotdate(::date) voor een basisformaat. Gebruik voor meerto_char(). -
GROUP BY 1is een syntaxisafkorting om te verwijzen naar de eerste uitvoerkolom. KanGROUP BY dayzijn ook, maar dat kan in strijd zijn met een bestaande kolom met dezelfde naam. OfGROUP BY date_trunc('month', date_col)::datemaar dat is te lang naar mijn smaak. -
Werkt met de beschikbare intervalargumenten voor
date_trunc(). -
count()produceert nooitNULL(0voor geen rijen), maar deLEFT JOINdoet.
Te retourneren0in plaats vanNULLin 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