SELECT f.id, f.name, b.fb_ct, t.tag_names
FROM foo f
LEFT JOIN (
SELECT foo_id AS id, count(*) AS fb_ct
FROM foo_bar
GROUP BY 1
) b USING (id)
LEFT JOIN (
SELECT target_id AS id, array_agg(name) AS tag_names
FROM tag
GROUP BY 1
) t USING (id)
ORDER BY f.id;
Tạo ra kết quả mong muốn.
-
Viết lại bằng
JOIN
rõ ràng cú pháp. Giúp cho việc đọc và hiểu (và gỡ lỗi) trở nên dễ dàng hơn rất nhiều. -
Bằng cách kết hợp với nhiều
1:n
các bảng, các hàng có liên quan sẽ nhân nhau tạo ra sản phẩm Descartes - đó là điều vô nghĩa rất tốn kém. Đây là mộtCROSS JOIN
ngoài ý muốn bằng proxy. Có liên quan: -
Để tránh điều này, hãy tham gia nhiều nhất một
n
-chuyển tới1
-bảng trước khi bạn tổng hợp (GROUP BY
). Bạn có thể tổng hợp hai lần, nhưng tổng hợpn
sẽ nhanh hơn và nhanh hơn -bảng riêng trước kết hợp họ với1
-bàn. -
Trái ngược với bản gốc của bạn (với
INNER JOIN
ngầm hiểu ). Tôi sử dụngLEFT JOIN
để tránh mất các hàng từfoo
không có hàng phù hợp trongfoo_bar
hoặc thẻtag
. -
Sau khi
CROSS JOIN
không mong muốn được xóa khỏi truy vấn, không cần thêmDISTINCT
nữa - giả sử rằngfoo.id
là duy nhất.