じゃあ次のステップに進もうか — ネストされたクエリをSQLで使ってみよう。今日は、それが何なのか、なんで必要なのか、どんな種類があるのか、そして現実世界でどう役立つのかを見ていくよ。
ネストされたクエリ(またはサブクエリ)っていうのは、他のSQLクエリの中で使われるSQLクエリのこと。マトリョーシカとかキャベツみたいな感じ:外側のクエリがあって、その中にもう一つ小さいクエリが隠れてる。サブクエリが先に実行されて、その結果が外側のクエリ(たまに「メイン」って呼ばれる)で使われるんだ。
例で見てみよう:
例1: どうやって動くの?
例えば、studentsテーブルがあって、こんなデータが入ってるとする:
| id | 名前 | 年齢 | グループ_id |
|---|---|---|---|
| 1 | アリサ | 20 | 1 |
| 2 | ボブ | 22 | 2 |
| 3 | クラーク | 21 | 1 |
| 4 | ディナ | 23 | 3 |
| 5 | エミリア | 22 | 2 |
それから、グループの名前が入ってるgroupsテーブルもある:
| id | 名前 |
|---|---|
| 1 | 数学クラス |
| 2 | 物理クラス |
| 3 | 文学クラス |
もし、学生が所属してるグループの名前を知りたいなら、ネストされたクエリを使えるよ:
SELECT 名前
FROM groups
WHERE id IN (
SELECT グループ_id
FROM students
WHERE 年齢 > 21
);
ここで何が起きてる?
ネストされたクエリ:
SELECT グループ_id
FROM students
WHERE 年齢 > 21
このクエリは、21歳より上の学生のグループ_idを全部選んでる。結果はグループIDのリスト、例えば[2, 3]みたいな感じ。
メインのクエリ:
SELECT 名前
FROM groups
WHERE id IN ([サブクエリの結果])
このクエリはサブクエリの結果を使って、idが2か3のグループの名前を返すよ。
結果:
物理クラス
文学クラス
まだよく分からない?まあ、当然だよね。でも心配しないで、今から全部説明するから!
まずシンプルなアイデアから始めよう — SELECTクエリの実行結果は、ある意味仮想テーブルなんだ。ちゃんとカラムもあるし、行もある。もうテーブルみたいなもんでしょ?
で、そのクエリの結果がテーブルなら、普通のテーブルと同じように使える。例えばJOINで使ったり、もっと複雑な構造でも使える。
ただし、名前がないのが問題。でも、カラムの式にも名前がないことあるし、それはalias(エイリアス)をつけて解決するよね。仮想テーブルにも同じことができる。
詳しくは次のレクチャーで — ネタバレはしないでおくね :P
ネストされたクエリの便利さ
複雑な課題をシンプルにできる。1つのテーブルだけじゃ欲しい情報が全部取れないこともある。サブクエリを使えば、まず中間結果を出して、それを使って最終データを取るって2段階に分けられる。
中間結果を扱える。ネストされたクエリは、データを処理する前に追加の計算が必要なときに便利。例えば最小値を探したり、合計を計算したり。
コードの読みやすさアップ。ネストされたクエリを使うと、特に大きなテーブルや複雑なロジックのときにコードが整理されて分かりやすくなる。
ネストされたクエリの主なタイプ
ネストされたクエリは、SQLクエリのいろんな場所で使える。どこで使うかによって、いくつかのタイプに分かれるよ。
SELECTの中のサブクエリ。カラムリストの中にサブクエリを書いて、値を計算するのに使う。例えば、結果に新しいカラムを追加したいときに便利。
例 — 学生の中で最大年齢のカラムを追加してみよう:
SELECT 名前, 年齢,
(SELECT MAX(年齢) FROM students) AS 最大_年齢
FROM students;
結果:
| 名前 | 年齢 | 最大_年齢 |
|---|---|---|
| アリサ | 20 | 23 |
| ボブ | 22 | 23 |
| クラーク | 21 | 23 |
| ディナ | 23 | 23 |
| エミリア | 22 | 23 |
FROMの中のサブクエリ。サブクエリを一時テーブルとして使う。まず集計や変換をしてから使いたいときに便利。
例 — 各グループごとの学生の平均年齢を計算してみよう:
SELECT tmp.グループ_id, tmp.平均_年齢
FROM (
SELECT グループ_id, AVG(年齢) AS 平均_年齢
FROM students
GROUP BY グループ_id
) AS tmp -- 一時テーブルにtmpってエイリアスをつけてる
WHERE tmp.平均_年齢 > 21;
結果:
| グループ_id | 平均_年齢 |
|---|---|
| 2 | 22.0 |
| 3 | 23.0 |
WHEREやHAVINGの中のサブクエリ。サブクエリを条件として使って、行をフィルタリングできる。よく使うのは、- レコードの存在チェックや値の比較とか。
例 — 平均年齢より上の学生を探してみよう:
SELECT 名前, 年齢
FROM students
WHERE 年齢 > (
SELECT AVG(年齢)
FROM students
);
結果:
| 名前 | 年齢 |
|---|---|
| ボブ | 22 |
| ディナ | 23 |
| エミリア | 22 |
ネストされたクエリを使うメリット
柔軟性アップ:ネストされたクエリを使うと、もっと複雑なデータ構造も扱えるようになる。
処理を段階的に分けられる:ロジックをサブクエリで分けることで、コードが読みやすくなる。
中間データにアクセスできる:データベースに一時テーブルを作らなくても、「その場で」データを処理できるよ。
GO TO FULL VERSION