英語607877 views
高校生物549842 views
中学社会667106 views
MathPython491378 views
ヒストリア284143 views
いろは2986023 views
教育148875 views
雑学1472593 views
中学英語808712 views
中学数学621382 views
Help
Tools

English

IN とサブクエリを組み合わせる

IN 演算子とサブクエリを組み合わせると、「別のテーブルから取得した値のリストに含まれるか」をチェックできます。

基本構文

SELECT * FROM テーブル
WHERE カラム IN (サブクエリ);

サブクエリが返す複数の値のどれかに一致すれば TRUE になります。

具体例

「注文したことがあるユーザー」を取得するには、こう書きます。

SELECT * FROM users
WHERE id IN (SELECT user_id FROM orders);

サブクエリが注文テーブルから user_id の一覧を取得し、その中に含まれる users.id を持つ行だけが返ります。

固定値の IN との違い

固定値を使う IN は、値を直接書きます。

-- 固定値
SELECT * FROM users WHERE city IN ('東京', '大阪', '名古屋');

-- サブクエリ
SELECT * FROM users WHERE city IN (SELECT city FROM target_cities);

サブクエリを使うと、条件を動的に取得できます。

NOT IN

NOT IN を使うと「含まれない」をチェックできます。

-- 注文したことがないユーザー
SELECT * FROM users
WHERE id NOT IN (SELECT user_id FROM orders);

NOT IN と NULL の罠

NOT IN を使うときは NULL に注意が必要です。サブクエリの結果に NULL が含まれていると、NOT IN は期待どおりに動きません。

-- orders.user_id に NULL があると、結果が 0 件になる可能性
SELECT * FROM users
WHERE id NOT IN (SELECT user_id FROM orders);

これは SQL の仕様です。NULL との比較は常に UNKNOWN になるため、NOT IN 全体が UNKNOWN になってしまいます。

サブクエリに NULL なし

正常に動作する

サブクエリに NULL あり

結果が 0 件になる可能性

回避するには、サブクエリで NULL を除外します。

SELECT * FROM users
WHERE id NOT IN (SELECT user_id FROM orders WHERE user_id IS NOT NULL);

または NOT EXISTS を使うほうが安全です。

SELECT * FROM users u
WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id);

パフォーマンスについて

IN とサブクエリの組み合わせは、サブクエリの結果が大きくなると遅くなることがあります。

小さい結果セット

IN + サブクエリでも問題ない

大きい結果セット

JOIN や EXISTS を検討したほうがよい

-- IN + サブクエリ
SELECT * FROM users WHERE id IN (SELECT user_id FROM orders);

-- JOIN で書き換え(重複除去が必要)
SELECT DISTINCT u.* FROM users u JOIN orders o ON u.id = o.user_id;

IN とサブクエリは直感的でわかりやすい書き方ですが、NOT IN の NULL 問題だけは覚えておきましょう。