【Day39】EXISTSとNOT EXISTSの使い方

投稿者: | 2025年9月20日

SQLの学習で「EXISTS」が出てくると一気に難しく感じた私ですが、考え方はシンプルなようです。
一言でいえば 「そのサブクエリに結果が存在するかどうかを調べる」 ための仕組みです。

1. EXISTSとは?

EXISTS は「サブクエリに1件以上のデータが存在するか」を判定します。

SELECT 列名
FROM テーブルA
WHERE EXISTS (
    SELECT *
    FROM テーブルB
    WHERE 条件
);
  • サブクエリに1行でも結果があれば → TRUE
  • 結果が0行なら → FALSE

例:部活に所属している学生を探す

SELECT 名前
FROM 学生 s
WHERE EXISTS (
    SELECT *
    FROM 部活 b
    WHERE s.学生ID = b.学生ID
);

👉 「学生テーブル」の中から、部活テーブルに存在する学生だけを取り出します。


2. NOT EXISTSとは?

逆に、サブクエリの結果が1件も存在しないときにTRUE になります。

SELECT 名前
FROM 学生 s
WHERE NOT EXISTS (
    SELECT *
    FROM 部活 b
    WHERE s.学生ID = b.学生ID
);

👉 部活に所属していない学生を探せます。


3. EXISTSとINの違い

似た使い方ができるのが IN句 です。

-- IN を使った例
SELECT 名前
FROM 学生
WHERE 学生ID IN (SELECT 学生ID FROM 部活);

ただし、大量データになると EXISTSの方が効率的 なケースが多いです。
→ EXISTSは「見つかった時点で検索終了」するのに対し、INはすべての値をリスト化する必要があるからです。


4. 練習問題

【問題1】

次のテーブルがあります。

学生(学生ID, 名前)
部活(学生ID, 部活名)

SQLを書いてください。

  1. 部活に所属している学生の名前を表示する
  2. 部活に所属していない学生の名前を表示する

解答1-1(所属している学生)

SELECT s.名前
FROM 学生 s
WHERE EXISTS (
    SELECT *
    FROM 部活 b
    WHERE s.学生ID = b.学生ID
);

解説

  • EXISTS はサブクエリに結果があるかどうかを確認する。
  • 学生テーブルの1行ごとに、部活テーブルに同じ学生IDがあればTRUE → その学生が結果に出る。

解答1-2(所属していない学生)

SELECT s.名前
FROM 学生 s
WHERE NOT EXISTS (
    SELECT *
    FROM 部活 b
    WHERE s.学生ID = b.学生ID
);

解説

  • NOT EXISTS はサブクエリの結果が0件のときにTRUEになる。
  • 部活テーブルに存在しない学生を取り出す。

【問題2】

注文(注文ID, 顧客ID, 日付)
顧客(顧客ID, 名前)

  1. 注文を一度もしたことがある顧客の名前を表示する
  2. 注文を一度もしたことがない顧客の名前を表示する

解答2-1(注文したことがある顧客)

SELECT c.名前
FROM 顧客 c
WHERE EXISTS (
    SELECT *
    FROM 注文 o
    WHERE c.顧客ID = o.顧客ID
);

解説

  • 顧客テーブルを基準に、注文テーブルに対応する行がある顧客だけを表示。
  • 「一度でも注文があれば結果に出る」。

解答2-2(注文したことがない顧客)

SELECT c.名前
FROM 顧客 c
WHERE NOT EXISTS (
    SELECT *
    FROM 注文 o
    WHERE c.顧客ID = o.顧客ID
);

解説

  • 注文テーブルに存在しない顧客 → まだ注文したことがない人。
  • 「新規顧客候補」などの分析に使える。

ちなみに・・・

この c.名前c. は、テーブルの別名(エイリアス) をつけて呼んでいるものです。


具体的に説明すると

SELECT c.名前
FROM 顧客 c
  • 顧客 というテーブルに c というあだ名(別名) をつけている
  • 以降は、c を書けば「顧客テーブルのことですよ」とSQLがわかる

つまり、

  • c.名前 = 顧客テーブルの「名前」列
  • c.顧客ID = 顧客テーブルの「顧客ID」列

なぜ別名を使うの?

  1. 短く書ける
    • 顧客.名前 と毎回書くより c.名前 のほうがスッキリ。
  2. 複数のテーブルを結合するとき便利 SELECT c.名前, o.日付 FROM 顧客 c JOIN 注文 o ON c.顧客ID = o.顧客ID;c は顧客、o は注文、と区別できるので混乱しない。
  3. 同じ列名が複数ある場合の衝突回避
    • 例えば「顧客ID」が両方のテーブルにあるとき、どっちのIDかを指定できる。

📌まとめると:
c.「顧客テーブルのことを、c って省略名で呼んでますよ」 という意味。


まとめ

  • EXISTS:サブクエリに1件でもデータがあればTRUE
  • NOT EXISTS:サブクエリに1件もデータがなければTRUE
  • 実務でも「未注文の顧客」「未登録のユーザー」などを調べるのによく使う

🔍 過去問例:平成26年春期 午前 問28

問題内容(簡略化)

テーブル:

  • 商品表(商品番号, 商品名, 単価等)
  • 在庫表(在庫番号, 商品番号, 在庫数等)

以下と同じ結果が得られる SQL 文を選びなさい。

SELECT 商品番号 
FROM 商品
WHERE 商品番号 NOT IN (SELECT 商品番号 FROM 在庫)

選択肢の中に、EXISTSNOT EXISTS を使ったものがあり、同じ結果となるものを選ぶ問題です。 基本情報技術者試験ドットコム+1


正解の論理

この SQL 文の意味は:

  • 「商品表 の中から、在庫表に 存在しない 商品番号 を表示せよ。」

すなわち、在庫表にその商品番号が 一度も出てこない商品 を選ぶ。
この “NOT IN サブ問合せ” を、 NOT EXISTS を使って書き換えると同じ意味になります。


EXISTSを使った書き換え例

SELECT 商品番号
FROM 商品 p
WHERE NOT EXISTS (
  SELECT *
  FROM 在庫 z
  WHERE p.商品番号 = z.商品番号
);
  • pz はテーブルの別名
  • サブクエリは「在庫テーブルに p.商品番号 が存在するかどうか」を調べる
  • NOT EXISTS を使って「存在しないもののみ」を取得

解答のポイント/注意点

  • NOT IN はNULLが入る可能性のある場合に動きが複雑になることがあるが、この問題では在庫表の商品番号がNULLでないことが前提。
  • EXISTS / NOT EXISTS は “相関副問合せ”(親クエリの行を使ってサブクエリを動かすもの)である。
  • 問題文をよく読み、「存在するかしないか」を問われているか/ “NOT” があるかに注意。

🔍 その他の出題例

ブログで見つかる他の SQL 過去問例から、「EXISTS / 副問合せ」が問われているものをまとめておきます:


🧸 幼稚園児にもわかるたとえ

  • 商品 = おもちゃ
  • 在庫 = 遊ぶおもちゃが棚にあるかどうか
  • 「棚にないおもちゃだけ持ってくる」 → NOT EXISTS のイメージ

✅ まとめ

項目キーワード
問題の意図存在するか/存在しないかを確認する
主に使う句EXISTS / NOT EXISTS / IN / NOT IN
書き換え可能性NOT IN ⇔ NOT EXISTS(NULL の有無など前提条件に注意)
選択肢での判断ポイントサブクエリの中でどのテーブル/どの列を参照しているか、NOT の有無、NULL の影響