Solusi yang tepat
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;
-
Gunakan
LEFT JOIN
, tentu saja. -
generate_series()
dapat menghasilkan tabel stempel waktu dengan cepat, dan sangat cepat. -
Biasanya lebih cepat untuk mengagregasi sebelum Anda bergabung. Saya baru-baru ini memberikan kasus uji di sqlfiddle.com dalam jawaban terkait ini:
- PostgreSQL - urutkan menurut larik
-
Keluarkan
timestamp
untukdate
(::date
) untuk format dasar. Untuk lebih banyak gunakanto_char()
. -
GROUP BY 1
adalah singkatan sintaks untuk referensi kolom output pertama. Bisa jadiGROUP BY day
juga, tapi itu mungkin bertentangan dengan kolom yang ada dengan nama yang sama. AtauGROUP BY date_trunc('month', date_col)::date
tapi itu terlalu panjang untuk seleraku. -
Bekerja dengan argumen interval yang tersedia untuk
date_trunc()
. -
count()
tidak pernah menghasilkanNULL
(0
tanpa baris), tetapiLEFT JOIN
tidak.
Untuk mengembalikan0
bukannyaNULL
di bagian luarSELECT
, gunakanCOALESCE(some_count, 0) AS some_count
. Panduan. -
Untuk solusi yang lebih umum atau interval waktu yang berubah-ubah pertimbangkan jawaban yang terkait erat ini:
- Cara terbaik untuk menghitung catatan dengan interval waktu sewenang-wenang di Rails+Postgres