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;
Produce el resultado deseado.
-
Reescribir con
JOIN
explícito sintaxis. Hace que sea mucho más fácil de leer y comprender (y depurar). -
Uniéndose a múltiples
1:n
tablas relacionadas, las filas se multiplicarían entre sí produciendo un producto cartesiano - que es una tontería muy cara. Es unCROSS JOIN
no intencionado por delegación. Relacionado: -
Para evitar esto, únete como máximo a uno
n
-tabla al1
-table antes de agregar (GROUP BY
). Podría agregar dos veces, pero es más limpio y rápido agregarn
-tablas por separado antes uniéndolos al1
-mesa. -
A diferencia de su original (con
INNER JOIN
implícito ). Yo usoLEFT JOIN
para evitar perder filas defoo
que no tienen una fila coincidente enfoo_bar
otag
. -
Una vez que el
CROSS JOIN
no deseado se elimina de la consulta, no es necesario agregarDISTINCT
más - suponiendo quefoo.id
es único.