Tidak kusut, disederhanakan, dan diperbaiki, mungkin terlihat seperti ini:
SELECT to_char(s.tag,'yyyy-mm') AS monat
, count(t.id) AS eintraege
FROM (
SELECT generate_series(min(date_from)::date
, max(date_from)::date
, interval '1 day'
)::date AS tag
FROM mytable t
) s
LEFT JOIN mytable t ON t.date_from::date = s.tag AND t.version = 1
GROUP BY 1
ORDER BY 1;
db<>main biola di sini
Di antara semua kebisingan, pengidentifikasi yang menyesatkan, dan format yang tidak konvensional, masalah sebenarnya tersembunyi di sini:
WHERE version = 1
Anda benar menggunakan RIGHT [OUTER] JOIN
. Tetapi menambahkan WHERE
klausa yang membutuhkan baris yang ada dari mytable
mengonversi RIGHT [OUTER] JOIN
ke [INNER] JOIN
secara efektif.
Pindahkan filter itu ke JOIN
kondisi untuk membuatnya bekerja.
Saya menyederhanakan beberapa hal lain saat melakukannya.
Lebih baik lagi
SELECT to_char(mon, 'yyyy-mm') AS monat
, COALESCE(t.ct, 0) AS eintraege
FROM (
SELECT date_trunc('month', date_from)::date AS mon
, count(*) AS ct
FROM mytable
WHERE version = 1
GROUP BY 1
) t
RIGHT JOIN (
SELECT generate_series(date_trunc('month', min(date_from))
, max(date_from)
, interval '1 mon')::date
FROM mytable
) m(mon) USING (mon)
ORDER BY mon;
db<>main biola di sini
Jauh lebih murah untuk menggabungkan terlebih dahulu dan bergabung kemudian - bergabung dengan satu baris per bulan, bukan satu baris per hari.
Lebih murah untuk mendasarkan GROUP BY
dan ORDER BY
pada date
nilai alih-alih text
yang diberikan .
count(*)
sedikit lebih cepat dari count(id)
, sementara setara dalam ini kueri.
generate_series()
sedikit lebih cepat dan lebih aman jika didasarkan pada timestamp
bukannya date
. Lihat:
- Membuat deret waktu antara dua tanggal di PostgreSQL