SQLで複数テーブルからデータを取るとき、JOINで書く場合とサブクエリで書く場合があります。どちらでも同じ結果が得られることも多いですが、どう使い分けるのが良いのでしょうか?パフォーマンスの違いも気になります。
基本方針は「複数テーブルの列を組み合わせて表示したいならJOIN」「絞り込み条件として別テーブルを使うだけならサブクエリ(またはEXISTS)」です。
例:注文があるユーザーだけ取り出す場合。
-- JOIN(重複が出るのでDISTINCTが要ることも)
SELECT DISTINCT u.*
FROM users u
JOIN orders o ON o.user_id = u.id;
-- EXISTS(存在チェックだけなので明快・速いことが多い)
SELECT *
FROM users u
WHERE EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id
);
パフォーマンスは実行計画次第で、最近のDBはどちらも最適化してくれることが多いです。まずは意図が読みやすいほうを選び、遅ければEXPLAINで確認するのが実務的です。
相関サブクエリを大量行に対して回すと遅くなりがちです。件数チェックはINよりEXISTSのほうが早期に打ち切れて有利なケースが多いです。
集計値を条件に使いたいとき(例:合計が1万円以上のユーザー)はサブクエリ/CTEが読みやすいです。WITH句で名前を付けると可読性がぐっと上がります。
JOINは「横に列を増やす」、サブクエリは「縦に絞り込む」とイメージすると使い分けやすいです。
PostgreSQLならEXPLAIN ANALYZEで実測できます。感覚ではなく実行計画で判断しましょう。