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;
Дава желания резултат.
-
Пренапишете с изричен
JOINсинтаксис. Прави го много по-лесно за четене и разбиране (и отстраняване на грешки). -
Чрез присъединяване към множество
1:nсвързани таблици, редовете ще се умножават взаимно, създавайки декартово произведение - което е много скъпа глупост. Това е нежеланоCROSS JOINчрез пълномощник. Свързани: -
За да избегнете това, присъединете се към най-много един
n-таблица към1-таблица, преди да обобщите (GROUP BY). Можете да обобщите два пъти, но е по-чисто и по-бързо да обобщитеn-таблици отделно преди присъединявайки ги към1- маса. -
За разлика от вашия оригинал (с имплицитно
INNER JOIN). ИзползвамLEFT JOINза да избегнете загуба на редове отfooкоито нямат съответстващ ред вfoo_barилиtag. -
След нежеланото
CROSS JOINе премахнат от заявката, няма нужда от добавяне наDISTINCTповече - ако приемем, чеfoo.idе уникален.