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 comJOINexplícito sintaxe. Torna muito mais fácil de ler e entender (e depurar).
-
Ao ingressar em vários1:ntabelas relacionadas, as linhas se multiplicariam produzindo um produto cartesiano - o que é um absurdo muito caro. É umCROSS JOINnã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 JOINimplícito) ). Eu usoLEFT JOINpara evitar perder linhas defooque não têm linha correspondente emfoo_baroutag.
-
Uma vez que oCROSS JOINnão intencional for removido da consulta, não há necessidade de adicionarDISTINCTmais - assumindo quefoo.idé único.