Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
サブクエリ(スカラー・行)
クエリの中に別の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』を使います。外側のクエリを参照するサブクエリは『相関サブクエリ』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。