Không có vấn đề, đơn giản hóa và cố định, nó có thể trông giống như sau:
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 <> fiddle here
Trong số tất cả các nhiễu, số nhận dạng gây hiểu lầm và định dạng độc đáo, vấn đề thực sự đã được ẩn ở đây:
WHERE version = 1
Bạn đã sử dụng đúng RIGHT [OUTER] JOIN
. Nhưng thêm một WHERE
mệnh đề yêu cầu một hàng hiện có từ mytable
chuyển đổi RIGHT [OUTER] JOIN
tới một [INNER] JOIN
một cách hiệu quả.
Di chuyển bộ lọc đó vào JOIN
điều kiện để làm cho nó hoạt động.
Tôi đã đơn giản hóa một số thứ khác trong khi làm việc đó.
Tốt hơn, nhưng
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 <> fiddle here
Sẽ rẻ hơn nhiều nếu tổng hợp trước và tham gia sau - tham gia một hàng mỗi tháng thay vì một hàng mỗi ngày.
Rẻ hơn khi đặt cơ sở GROUP BY
và ORDER BY
vào ngày date
giá trị thay vì text
được hiển thị .
count(*)
nhanh hơn một chút so với count(id)
, trong khi tương đương trong this truy vấn.
generate_series()
nhanh hơn và an toàn hơn một chút khi dựa trên timestamp
thay vì date
. Xem:
- Tạo chuỗi thời gian giữa hai ngày trong PostgreSQL