SELECT句のサブクエリ
SELECT句のサブクエリ とは
SELECT句にサブクエリを記述し、より高度なデータ抽出を実践します。本レッスンでは、SELECT句のサブクエリ の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。
なぜ重要か
「商品の価格と一緒に、全商品の平均価格も併記したい」「各注文の隣に、その顧客の合計購入額を表示したい」のように、行ごとに 付加情報 を 1 列として追加したいことがあります。SELECT 句のサブクエリ(スカラーサブクエリ)は、まさにこのときに使います。1 行 1 列の値だけを返すサブクエリを、SELECT のリストにそのまま挿入することで、レポート系の SQL が驚くほど書きやすくなります。
構文・キーワード解説
SELECT 句のサブクエリは 必ず 1 行 1 列 の値を返す必要があります(スカラー値)。
SQL クエリ
SELECT
name,
price,
(SELECT AVG(price) FROM products) AS overall_avg,
price - (SELECT AVG(price) FROM products) AS diff_from_avg
FROM products;AS で列名をつけるのを忘れないでください。サブクエリのままでは長すぎて読みづらく、外側からの参照もできなくなります。
ステップごとの動作
スカラーサブクエリは、外側の行 1 件ごとに 1 つの値を埋め込むイメージです。非相関なら 1 回だけ、相関なら行ごとに評価されます。
代表例
平均価格と差額を並べて表示
SQL クエリ
SELECT
name,
price,
(SELECT ROUND(AVG(price)) FROM products) AS avg_price,
price - (SELECT ROUND(AVG(price)) FROM products) AS diff
FROM products
ORDER BY price DESC;各行に「全体平均」と「差額」を並べることで、行単位で平均との位置関係が一目でわかります。レポートでよくある形です。
顧客ごとの合計購入額を相関サブクエリで埋める
SQL クエリ
SELECT
c.id,
c.name,
(SELECT COALESCE(SUM(amount), 0) FROM orders o WHERE o.customer_id = c.id) AS total
FROM customers c
ORDER BY c.id;o.customer_id = c.id で外側の行と内側を関連付けています。これが相関サブクエリです。LEFT JOIN + GROUP BY で書き換えることもできますが、見た目はサブクエリのほうがすっきりすることが多いです。
スカラーサブクエリの注意点
注意 スカラーサブクエリが 2 行以上返すと、実行時に
Subquery returns more than 1 rowエラーになります。LIMIT 1 を付けるか、集計関数で 1 行にまとめてから返すように設計しましょう。
SQL クエリ
-- NG(複数行返る可能性)
SELECT name, (SELECT price FROM products WHERE category = 'X') FROM ...;
-- OK(集計で 1 行に絞る)
SELECT name, (SELECT MAX(price) FROM products WHERE category = 'X') FROM ...;JOIN との比較
| 観点 | スカラーサブクエリ | LEFT JOIN + GROUP BY |
|---|---|---|
| 直感性 | 1 行に 1 値を埋めるだけ | 複数行を畳み込むイメージ |
| 集計が複数あるとき | 列ごとにサブクエリを書く | 1 回の集計で複数列を取れる |
| パフォーマンス | 1 列なら速い | 多くの列を取るときに有利 |
スカラーサブクエリは「列を 1 つ足したいだけ」ならとても読みやすい。複数の集計列を一度に欲しい場合は LEFT JOIN + GROUP BY のほうが効率が良い。
相関サブクエリのコストに注意
スカラーサブクエリを 相関 で書くと、外側の行ごとに内側が評価されます。行数が少ないうちは問題ないですが、数万件規模では LEFT JOIN + GROUP BY のほうが速いことが多いので、実行計画を確認する習慣をつけましょう。
SQL クエリ
-- LEFT JOIN 版(複数列をまとめて出すときに有利)
SELECT c.id, c.name,
COALESCE(SUM(o.amount), 0) AS total,
COUNT(o.id) AS order_count
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
GROUP BY c.id, c.name
ORDER BY c.id;相関スカラーサブクエリは「行ごとの繰り返し」になりやすいので、CSV 出力やレポートで多くの行を返すクエリでは特に注意する。
「1 列だけ追加」「結果行数が少ない」場合はスカラーサブクエリ、「複数列をまとめて」「行数が多い」場合は LEFT JOIN + GROUP BY と覚えると判断しやすい。
まとめ
- SELECT 句のサブクエリ(スカラーサブクエリ)は 1 行 1 列の値を返す
- 各行に集計値や別テーブルの値を付加するのに便利
- 相関サブクエリにすると行ごとに評価されるため、外側との関連条件を書ける
- 2 行以上返すサブクエリはエラーになるので、必ず単一値に絞る
- 行数や列数が増えたら LEFT JOIN + GROUP BY を検討する
次のレッスン
次は WITH句(CTE)の活用 です。SQLのWITH句(CTE)の構文と、具体的な活用方法について学習します。
事前確認 — 進む前に次の 3 つができることを確認しましょう。
- SELECT サブクエリ の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (30 秒)
Q. SELECT サブクエリ とは何か、1 文で説明してください。
A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。
関連レッスン
テーブル構造
schema.sql
CREATE TABLE customers (
id INT PRIMARY KEY,
name VARCHAR(40)
);
CREATE TABLE orders (
id INT PRIMARY KEY,
customer_id INT,
amount INT
);
INSERT INTO customers VALUES
(1, '佐藤'),
(2, '鈴木'),
(3, '田中'),
(4, '高橋');
INSERT INTO orders VALUES
(101, 1, 3000),
(102, 1, 1500),
(103, 2, 8000),
(104, 4, 5000),
(105, 4, 2500);期待される出力
| id | name | total_amount |
|---|---|---|
| 1 | 佐藤 | 4500 |
| 2 | 鈴木 | 8000 |
| 3 | 田中 | 0 |
| 4 | 高橋 | 7500 |