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
プロキシによる。関連: -
これを回避するには、最大で1つ参加します。
n
-1
へのテーブル -集計する前のテーブル(GROUP BY
)。 2回集計することもできますが、n
を集計する方がクリーンで高速です。 -個別に前のテーブル それらを1
に結合します -テーブル。 -
オリジナルとは対照的に(暗黙の
INNER JOIN
)。LEFT JOIN
を使用していますfoo
から行が失われないようにするためfoo_bar
に一致する行がない またはtag
。 -
意図しない
CROSS JOIN
クエリから削除された場合、DISTINCT
を追加する必要はありません。 これ以上-foo.id
と仮定します ユニークです。