本文へスキップ
BecomeCoder

SQL データ操作 (DML)コース · 第3章 テーブルをつなぐ · レッスン14

サブクエリ ― クエリの中のクエリ

ブラウザで完結

導入

「平均より高い商品は?」――この問いに答えるには、まず平均を求め、次にそれより高いものを絞り込むという2段階が必要です。クエリを2回に分けて数字を書き写してもよいのですが、SQL なら1つの文にまとめられます。カッコの中に入れた「もう1つの SELECT」を サブクエリ(副問い合わせ) と呼びます。

説明

サブクエリはカッコ ( ) で囲んで書きます。内側の SELECT が先に実行され、その結果が外側のクエリの値として使われます。

flowchart LR
    Inner["内側: (SELECT AVG(price) FROM products)<br/>→ まず平均 24357 を計算"]
    Inner -->|"その値を使って"| Outer["外側: WHERE price > 24357<br/>→ 平均より高い商品を絞り込む"]
SELECT name, price
FROM products
WHERE price > (SELECT AVG(price) FROM products);

このように1つの値を返すサブクエリは、=> の右側にそのまま置けます。サブクエリが複数の行を返すときは、レッスン4で学んだ IN と組み合わせます。「一度でも注文された商品」はこう書けます。

SELECT name FROM products
WHERE id IN (SELECT product_id FROM order_items);

内側が「注文明細に登場する product_id の一覧」を返し、外側が「その一覧に含まれる商品」を取り出します。逆に NOT IN にすれば「一度も注文されていない商品」(在庫0の Webカメラなど)を見つけられます。

JOIN(レッスン10〜13)でも似たことができます。目安は、他の表の列も表示したいなら JOIN絞り込みの条件に使うだけならサブクエリ。どちらでも書ける場面は多いので、まずは読めて書けることが大切です。

やってみよう

初期表示のクエリを実行して、平均より高い商品だけが出ることを確認しましょう。次に内側の (SELECT AVG(price) FROM products) だけを単独で実行して、「先に計算される値」の正体を見てみてください。

演習

users テーブルから、年齢(age)が全会員の平均より高い会員nameage を取り出してください。

ヒント1を見る

平均はサブクエリ (SELECT AVG(age) FROM users) で求め、WHERE age > の右側に置きます。

ヒント2を見る

SELECT name, age FROM users WHERE age > (SELECT AVG(age) FROM users);

実際に動かしてみよう

下のエディタにクエリを書いて「実行」を押すと、ブラウザ内のSQLiteで結果が表示されます。本文の例をそのまま試したり、書き換えたりしてみましょう。

SQL — ブラウザ内で実行(SQLite)

ブラウザ内でSQLを動かす環境(SQLite)を読み込みます(初回のみ一瞬)。
スクロールして表示された時点でも自動で読み込まれます。