Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

IN / EXISTS

サブクエリの結果と値を照合するための演算子です。『IN』は値がリストや結果セットに含まれるかを判定し、『EXISTS』はサブクエリが1行以上返すかを判定します。

構文
-- IN: 値がサブクエリの結果に含まれるかを判定します。
SELECT 列名 FROM テーブル
WHERE 列名 IN (SELECT 列名 FROM サブクエリ);

-- NOT IN: 値がサブクエリの結果に含まれない行を取得します。
SELECT 列名 FROM テーブル
WHERE 列名 NOT IN (SELECT 列名 FROM サブクエリ);

-- EXISTS: サブクエリが1行以上返す場合に真になります。
SELECT 列名 FROM テーブル AS a
WHERE EXISTS (
    SELECT 1 FROM サブクエリ WHERE サブクエリ.キー = a.キー
);

-- NOT EXISTS: サブクエリが0行の場合に真になります。
SELECT 列名 FROM テーブル AS a
WHERE NOT EXISTS (
    SELECT 1 FROM サブクエリ WHERE サブクエリ.キー = a.キー
);
構文一覧
構文概要
IN (SELECT ...)値がサブクエリの結果に含まれる行を返します。
NOT IN (SELECT ...)値がサブクエリの結果に含まれない行を返します。NULLが混在すると意図しない結果になります。
EXISTS (SELECT ...)サブクエリが1行以上返す場合に真となります。
NOT EXISTS (SELECT ...)サブクエリが0行の場合に真となります。
サンプルコード
-- 注文を持つ顧客を IN で取得します。
SELECT 顧客名
FROM 顧客
WHERE 顧客ID IN (SELECT DISTINCT 顧客ID FROM 注文);

-- 一度も注文していない顧客を NOT IN で取得します。
SELECT 顧客名
FROM 顧客
WHERE 顧客ID NOT IN (
    SELECT 顧客ID FROM 注文 WHERE 顧客ID IS NOT NULL
);

-- EXISTS で注文がある顧客を取得します(大量データで高速)。
SELECT c.顧客名
FROM 顧客 AS c
WHERE EXISTS (
    SELECT 1 FROM 注文 AS o WHERE o.顧客ID = c.顧客ID
);

-- NOT EXISTS で在庫がない商品カテゴリを取得します。
SELECT cat.カテゴリ名
FROM カテゴリ AS cat
WHERE NOT EXISTS (
    SELECT 1 FROM 商品 AS p WHERE p.カテゴリID = cat.カテゴリID
);
実行結果
-- 注文がある顧客(IN / EXISTS どちらも同じ結果)。
顧客名
-----------
山田 太郎
鈴木 花子
佐藤 次郎

-- 一度も注文していない顧客。
顧客名
-----------
田中 恵
高橋 一郎
データベース別の書き方

『IN』『NOT IN』『EXISTS』『NOT EXISTS』の構文は主要なデータベースで共通して使用できます。

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

ただし、テーブルの別名(エイリアス)に『AS』を使えるかはデータベースによって異なります。Oracle では『FROM テーブル名 別名』のように『AS』を省略して記述します。

-- Oracle(テーブルエイリアスにASを使わない)
SELECT c.顧客名
FROM 顧客 c
WHERE EXISTS (
    SELECT 1 FROM 注文 o WHERE o.顧客ID = c.顧客ID
);
概要

『IN』と『EXISTS』は同じ結果を返すことが多いですが、パフォーマンス特性が異なります。サブクエリの結果が大量行になる場合は『EXISTS』の方が高速なことが多いです。『EXISTS』はサブクエリが1行でも見つかった時点で評価を打ち切るためです。

『NOT IN』はサブクエリの結果に NULL が1件でも含まれると、すべての行が FALSE と評価されて0件になります。これは NULL との比較が UNKNOWN を返す SQL の仕様によるものです。NULL が混在する可能性がある場合は『NOT EXISTS』を使うか、サブクエリに『WHERE 列 IS NOT NULL』を追加してください。

サブクエリで単一値を返す比較は『サブクエリ(スカラー・行)』を、全値・任意値との比較は『ALL / ANY』を参照してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。