Richtige Lösung
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;
-
Verwenden Sie
LEFT JOIN
, natürlich. -
generate_series()
kann spontan und sehr schnell eine Tabelle mit Zeitstempeln erstellen. -
Es ist im Allgemeinen schneller, vorher zu aggregieren du nimmst teil. Ich habe kürzlich einen Testfall auf sqlfiddle.com in dieser verwandten Antwort bereitgestellt:
- PostgreSQL - Sortieren nach einem Array
-
Übertragen Sie den
timestamp
bisdate
(::date
) für ein Basisformat. Verwenden Sie für mehrto_char()
. -
GROUP BY 1
ist eine Syntax-Kurzform, um auf die erste Ausgabespalte zu verweisen. KönnteGROUP BY day
sein auch, aber das könnte mit einer vorhandenen Spalte mit demselben Namen in Konflikt stehen. OderGROUP BY date_trunc('month', date_col)::date
aber das ist mir zu lang. -
Funktioniert mit den verfügbaren Intervallargumenten für
date_trunc()
. -
count()
erzeugt niemalsNULL
(0
für keine Zeilen), sondern derLEFT JOIN
tut.
Um0
zurückzugeben stattNULL
im äußerenSELECT
, verwenden SieCOALESCE(some_count, 0) AS some_count
. Das Handbuch. -
Für eine allgemeinere Lösung oder beliebige Zeitintervalle Betrachten Sie diese eng verwandte Antwort:
- Der beste Weg, Datensätze in Rails+Postgres nach beliebigen Zeitintervallen zu zählen