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
JOINexplícito sintaxis. Hace que sea mucho más fácil de leer y comprender (y depurar). -
Uniéndose a múltiples
1:ntablas relacionadas, las filas se multiplicarían entre sí produciendo un producto cartesiano - que es una tontería muy cara. Es unCROSS JOINno 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 JOINimplícito ). Yo usoLEFT JOINpara evitar perder filas defooque no tienen una fila coincidente enfoo_barotag. -
Una vez que el
CROSS JOINno deseado se elimina de la consulta, no es necesario agregarDISTINCTmás - suponiendo quefoo.ides único.