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;
Menghasilkan hasil yang diinginkan.
-
Tulis ulang dengan eksplisit
JOIN
sintaksis. Membuatnya lebih mudah untuk dibaca dan dipahami (dan di-debug). -
Dengan bergabung ke beberapa
1:n
tabel terkait, baris akan saling mengalikan menghasilkan produk Cartesian - yang sangat mahal omong kosong. Ini adalahCROSS JOIN
yang tidak disengaja oleh proxy. Terkait: -
Untuk menghindari ini, bergabunglah paling banyak satu
n
-tabel ke1
-tabel sebelum Anda mengagregasi (GROUP BY
). Anda dapat mengagregasi dua kali, tetapi lebih bersih dan lebih cepat untuk mengagregasin
-tabel secara terpisah sebelum menggabungkan mereka ke1
-meja. -
Berbeda dengan aslinya (dengan
INNER JOIN
implisit) ). Saya menggunakanLEFT JOIN
untuk menghindari kehilangan baris darifoo
yang tidak memiliki baris yang cocok difoo_bar
atautag
. -
Setelah
CROSS JOIN
yang tidak diinginkan dihapus dari kueri, tidak perlu menambahkanDISTINCT
lagi - dengan asumsi bahwafoo.id
unik.