サブクエリとは

このレッスンで分かること

  • サブクエリは丸括弧で囲んだ SELECT 文を別のクエリに埋め込む書き方です
  • 書ける場所は WHERE / FROM / SELECT / WITH の 4 か所
  • 非相関は 1 回だけ実行、相関は外側の行ごとに評価されます

サブクエリ とは

SQL文の中でさらにSQL文を使う、サブクエリの概念を学びます。本レッスンでは、サブクエリ の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

なぜ重要か

ビジネス現場の問い合わせは「平均より売れている商品は?」「最後に購入された注文の合計は?」のように、集計結果や別テーブルの結果を条件にして絞り込むものが多いです。1 本の SELECT 文だけでは表現が難しいこうした問題を、SQL ではクエリの中にもう一つクエリを埋め込むことで解決します。これがサブクエリ(副問い合わせ)です。サブクエリを使えば一時テーブルを作らずに、入れ子のロジックを 1 つの文に閉じ込められます。本レッスンでは「サブクエリとは何か」「どこに書けるか」「内側と外側の評価順序」を整理し、次レッスン以降の WHERE 句/FROM 句/SELECT 句/CTE への足場を固めます。

サブクエリの基本構文

サブクエリは「丸括弧で囲んだ SELECT 文」で、外側のクエリの一部として扱われます。書ける場所は大きく分けて 4 か所です。

SQL クエリ

-- (1) WHERE 句 SELECT name FROM products WHERE price > (SELECT AVG(price) FROM products); -- (2) FROM 句 SELECT category, top_price FROM ( SELECT category, MAX(price) AS top_price FROM products GROUP BY category ) AS t; -- (3) SELECT 句 SELECT name, (SELECT AVG(price) FROM products) AS overall_avg FROM products; -- (4) WITH 句(CTE) WITH expensive AS ( SELECT * FROM products WHERE price >= 1000 ) SELECT * FROM expensive;
書く場所用途
WHERE集計値や 1 行の値を条件に使う
FROMサブクエリの結果を一時テーブル扱い
SELECT行ごとに付ける派生列を計算
WITH (CTE)名前付きで再利用しやすい中間結果

内側と外側の評価順序

基本のサブクエリ(非相関サブクエリ)は 内側が先に 1 回実行され、その結果が定数として外側に渡される という流れになります。これが理解できると、「WHERE の中の SELECT が毎行ごとに走るのでは?」という不安が消えます。

diagram (will load when visible)

図の流れを順序リストで書き直すと、次の通りです。

  1. 内側のサブクエリを実行する (非相関なら 1 回だけ)
  2. サブクエリの結果を 1 つの定数として取り出す
  3. 外側のクエリに、その定数を代入する
  4. 外側のクエリを実行する
  5. 最終結果が返る

相関サブクエリ(後のレッスンで扱う)になると、内側が外側の行ごとに評価されるため動きが変わります。まずは「非相関は 1 回だけ実行される」と覚えてください。

代表例

平均価格より高い商品を取り出す

SQL クエリ

SELECT name, price FROM products WHERE price > (SELECT AVG(price) FROM products) ORDER BY price DESC;

内側で全商品の平均価格が計算され、その値を使って外側で「平均より高い行」だけ取り出します。WHERE price > 850.0 という SQL を書いたのと同じ意味ですが、平均が変わっても自動的に追従します。

売上が最大のカテゴリの商品名を表示する

SQL クエリ

SELECT name, category FROM products WHERE category = ( SELECT category FROM products GROUP BY category ORDER BY SUM(price) DESC LIMIT 1 );

サブクエリは「売上合計が最大のカテゴリ名」を 1 つ返し、それと一致する商品行を抽出します。

サブクエリと JOIN の使い分け

サブクエリと JOIN は似た問題を解決しますが、得意分野が違います。

観点サブクエリJOIN
主用途集計値や 1 行の値で絞り込む複数テーブルの行を組み合わせる
可読性ロジックを上下に分けやすい1 文が横に長くなりがち
パフォーマンス結果が小さければ高速インデックスが効きやすい

「結果を 1 個の値で絞り込みたい」「先に集計してから絞り込みたい」ときはサブクエリが読みやすい。「複数テーブルから列を並べたい」ときは JOIN が向く。

よくある落とし穴

サブクエリが複数行を返すのに = で比較すると Subquery returns more than 1 row エラーになります。複数行を返すサブクエリには IN ANY ALL EXISTS を使いましょう。

FROM 句のサブクエリには必ず別名(エイリアス)が必要です。FROM (SELECT ...) AS t のように AS t をつけ忘れると構文エラーになります。

非相関サブクエリと相関サブクエリ

サブクエリは外側のクエリを参照するかどうかで 2 種類に分類できます。次のレッスン以降で本格的に登場する区別なので、ここで概要だけ押さえておきましょう。

  • 非相関サブクエリ: 内側だけで完結する。SELECT AVG(price) FROM products のように外側の列を参照しない
  • 相関サブクエリ: 外側の行を参照する。SELECT 1 FROM orders o WHERE o.customer_id = c.id のように内側で c.id を使う

非相関は内側が 1 回だけ評価されますが、相関は外側の行ごとに評価されるため、データ件数が多いとパフォーマンスへの影響が大きくなります。「相関にする必要があるのか?」を毎回意識するクセを付けると、無駄な相関サブクエリを避けられます。

非相関サブクエリは外側に依存しないため単独でも実行できる。動作を確認したいときは内側だけ取り出して試してみると安心。

この章のポイント

ここまでの要点 サブクエリは ( SELECT ... ) を 4 か所 (WHERE/FROM/SELECT/WITH) に書ける。非相関は 1 回、相関は行ごと。複数行を返すなら IN EXISTS を使う。

まとめ

  • サブクエリは「丸括弧で囲んだ SELECT 文」を別のクエリの中に埋め込む書き方
  • 書ける場所は WHERE / FROM / SELECT / WITH の 4 か所
  • 非相関サブクエリは内側が先に 1 回実行され、結果が定数として外側に渡る
  • 相関サブクエリは外側の行ごとに評価されるためコストに注意
  • 1 個の値で絞り込みたいときはサブクエリ、行を並べたいときは JOIN が読みやすい

次のレッスン

次は WHERE句のサブクエリ です。WHERE句の中でサブクエリを使う方法を、実践的な例を通して学びます。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

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

理解度チェック (30 秒)

Q. サブクエリ概念 とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン

テーブル構造

schema.sql

CREATE TABLE products ( id INT PRIMARY KEY, name VARCHAR(50), category VARCHAR(30), price INT ); INSERT INTO products VALUES (1, 'シャープペン', '文具', 200), (2, 'ノート', '文具', 350), (3, '万年筆', '文具', 5000), (4, 'マグカップ', '雑貨', 1200), (5, 'タンブラー', '雑貨', 2500), (6, 'ワイヤレスマウス', '家電', 3200), (7, 'キーボード', '家電', 6800);

期待される出力

nameprice
キーボード6800
万年筆5000
ワイヤレスマウス3200

ヒント

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