I have three tables:
CREATE TABLE foo (
id bigint PRIMARY KEY,
name text NOT NULL
);
CREATE TABLE foo_bar (
id bigint PRIMARY KEY,
foo_id bi
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;
Produces the desired result.
Rewrite with explicit JOIN
syntax. Makes it so much easier to read and understand (and debug).
By joining to multiple 1:n
related tables, rows would multiply each other producing a Cartesian product - which is very expensive nonsense. It's an unintended CROSS JOIN
by proxy. Related:
To avoid this, join at most one n
-table to the 1
-table before you aggregate (GROUP BY
). You could aggregate two times, but it's cleaner and faster to aggregate n
-tables separately before joining them to the 1
-table.
As opposed to your original (with implicit INNER JOIN
). I use LEFT JOIN
to avoid losing rows from foo
that have no matching row in foo_bar
or tag
.
Once the unintended CROSS JOIN
is removed from the query, there is no need for adding DISTINCT
any more - assuming that foo.id
is unique.