導入
「平均より高い商品は?」――この問いに答えるには、まず平均を求め、次にそれより高いものを絞り込むという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)が全会員の平均より高い会員の name と age を取り出してください。
ヒント1を見る
平均はサブクエリ (SELECT AVG(age) FROM users) で求め、WHERE age > の右側に置きます。
ヒント2を見る
SELECT name, age FROM users WHERE age > (SELECT AVG(age) FROM users);