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;
Produz o resultado desejado.
-
Reescreva comJOIN
explícito sintaxe. Torna muito mais fácil de ler e entender (e depurar).
-
Ao ingressar em vários1:n
tabelas relacionadas, as linhas se multiplicariam produzindo um produto cartesiano - o que é um absurdo muito caro. É umCROSS JOIN
não intencional por procuração. Relacionado:
-
Para evitar isso, participe de no máximo umn
-table para o1
-table antes de agregar (GROUP BY
). Você pode agregar duas vezes, mas é mais simples e rápido agregarn
-tables separadamente antes juntando-os ao1
-tabela.
-
Ao contrário do original (comINNER JOIN
implícito) ). Eu usoLEFT JOIN
para evitar perder linhas defoo
que não têm linha correspondente emfoo_bar
outag
.
-
Uma vez que oCROSS JOIN
não intencional for removido da consulta, não há necessidade de adicionarDISTINCT
mais - assumindo quefoo.id
é único.