Caution

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

  1. トップページ
  2. SQL辞典
  3. サブクエリ(スカラー・行)

サブクエリ(スカラー・行)

クエリの中に別のSELECT文を埋め込んだものをサブクエリと呼びます。スカラーサブクエリは必ず1列1行の単一値を返し、行サブクエリは1行複数列を返します。

構文
-- スカラーサブクエリ: SELECT列・WHERE条件・SET句などに単一値として埋め込みます。
SELECT 列名, (SELECT 集計関数(...) FROM ...) AS エイリアス
FROM テーブル;

-- WHERE句でスカラーサブクエリを使います。
SELECT 列名
FROM テーブル
WHERE 列名 = (SELECT 単一値を返すSELECT文);

-- 行サブクエリ: 複数列を比較します。
SELECT 列名
FROM テーブル
WHERE (列A, 列B) = (SELECT 列A, 列B FROM ... LIMIT 1);
構文一覧
種類概要
スカラーサブクエリ1列1行の単一値を返すサブクエリです。SELECT列・WHERE・SET句などに使えます。
行サブクエリ1行複数列を返すサブクエリです。行値式と組み合わせて複数列を一度に比較できます。
サンプルコード
-- 各社員の給与と全社員の平均給与を並べて表示します(スカラーサブクエリ)。
SELECT
    社員名,
    給与,
    (SELECT AVG(給与) FROM 社員) AS 平均給与,
    給与 - (SELECT AVG(給与) FROM 社員) AS 平均との差
FROM 社員
ORDER BY 給与 DESC;

-- 最も給与が高い社員を取得します。
SELECT 社員名, 給与
FROM 社員
WHERE 給与 = (SELECT MAX(給与) FROM 社員);

-- 最新注文と同じ顧客ID・商品IDを持つ注文を行サブクエリで検索します。
SELECT 注文ID, 顧客ID, 商品ID, 注文日
FROM 注文
WHERE (顧客ID, 商品ID) = (
    SELECT 顧客ID, 商品ID
    FROM 注文
    ORDER BY 注文日 DESC
    LIMIT 1
);
実行結果
-- 平均給与との比較結果。
社員名     | 給与      | 平均給与  | 平均との差
-----------+-----------+-----------+-----------
鈴木 花子  | 620000    | 480000    | 140000
山田 太郎  | 540000    | 480000    | 60000
佐藤 次郎  | 420000    | 480000    | -60000
田中 恵    | 340000    | 480000    | -140000

-- 最高給与の社員。
社員名     | 給与
-----------+---------
鈴木 花子  | 620000
データベース別の書き方

スカラーサブクエリの構文は主要なデータベースで共通して使用できます。

-- MySQL・PostgreSQL・SQL Server・Oracle・SQLite 共通
SELECT 社員名, 給与, (SELECT AVG(給与) FROM 社員) AS 平均給与
FROM 社員
ORDER BY 給与 DESC;

行サブクエリで結果を1行に制限する書き方はデータベースごとに異なります。MySQL・PostgreSQL・SQLite は『LIMIT 1』を使用します。

-- MySQL・PostgreSQL・SQLite
SELECT 注文ID, 顧客ID, 商品ID
FROM 注文
WHERE (顧客ID, 商品ID) = (
    SELECT 顧客ID, 商品ID FROM 注文 ORDER BY 注文日 DESC LIMIT 1
);

Oracle は『FETCH FIRST 1 ROW ONLY』を使用します(12c 以降)。それ以前のバージョンでは『ROWNUM』で制限します。

-- Oracle(12c 以降)
SELECT 注文ID, 顧客ID, 商品ID
FROM 注文
WHERE (顧客ID, 商品ID) = (
    SELECT 顧客ID, 商品ID FROM 注文 ORDER BY 注文日 DESC
    FETCH FIRST 1 ROW ONLY
);

SQL Server は『TOP 1』を使用します。また、SQL Server は行サブクエリ(複数列の同時比較)に対応していないため、列ごとに個別のサブクエリで比較する必要があります。

-- SQL Server(行サブクエリ非対応のため列ごとに比較)
SELECT 注文ID, 顧客ID, 商品ID
FROM 注文
WHERE 顧客ID = (SELECT TOP 1 顧客ID FROM 注文 ORDER BY 注文日 DESC)
  AND 商品ID = (SELECT TOP 1 商品ID FROM 注文 ORDER BY 注文日 DESC);
概要

『スカラーサブクエリ』は結果が必ず1列1行でなければなりません。2行以上を返すと実行時エラーになります。集計関数(MAX・MIN・AVG・COUNT)を使うと自然に1行になるため、スカラーサブクエリと相性が良いです。

スカラーサブクエリはSELECT句・WHERE句・HAVING句・SET句(UPDATE文)など多くの場所で使えます。SELECT句に書くと全行に対して毎回評価されるため、大量データに対しては JOIN や派生テーブルへの書き換えを検討してください。

複数行を返すサブクエリとの比較には『IN / EXISTS』や『ALL / ANY』を使います。外側のクエリを参照するサブクエリは『相関サブクエリ』を参照してください。

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