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 回だけ、相関なら行ごとに評価されます。

diagram (will load when visible)

代表例

平均価格と差額を並べて表示

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 つができることを確認しましょう。

  1. SELECT サブクエリ の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (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);

期待される出力

idnametotal_amount
1佐藤4500
2鈴木8000
3田中0
4高橋7500

ヒント

query.sql
query.sql
学習モード
コードの実行結果
データベースを初期化中...