SQLを学んでいると、「別のSQLで取得した結果を、さらに別のSQLで利用したい」という場面があります。
このようなときに使用するのが、**副問い合わせ(サブクエリ)**です。
今回は、サンプルテーブルを使って、SQLを実行しながら副問い合わせの動きを確認していきます。
1. 今回使用するテーブル
今回は、以下の2つのテーブルがすでに存在しているものとします。
employeeテーブル
| employee_id | employee_name | salary | department_id |
|---|---|---|---|
| 1 | 田中 | 300000 | 10 |
| 2 | 鈴木 | 400000 | 20 |
| 3 | 佐藤 | 500000 | 20 |
| 4 | 高橋 | 350000 | 10 |
| 5 | 伊藤 | 450000 | 30 |
departmentテーブル
| department_id | department_name | location |
|---|---|---|
| 10 | 営業部 | 東京 |
| 20 | 開発部 | 大阪 |
| 30 | 総務部 | 東京 |
| 40 | 企画部 | 東京 |
以降は、このデータを使って副問い合わせを実行します。
2. 副問い合わせとは
副問い合わせとは、SQL文の中に記述する別のSQL文です。
例えば、
全社員の平均給与より給与が高い社員を取得する
という処理を考えます。
まず、平均給与を取得します。
SELECT AVG(salary)
FROM employee;
実行結果は次のとおりです。
| AVG(salary) |
|---|
| 400000 |
平均給与は400,000円です。
この結果を利用して、
SELECT *
FROM employee
WHERE salary > 400000;
とすれば、平均給与より給与が高い社員を取得できます。
結果は、
| employee_id | employee_name | salary | department_id |
|---|---|---|---|
| 3 | 佐藤 | 500000 | 20 |
| 5 | 伊藤 | 450000 | 30 |
となります。
この2つのSQLを1つにまとめると、副問い合わせになります。
SELECT *
FROM employee
WHERE salary > (
SELECT AVG(salary)
FROM employee
);
実行結果
| employee_id | employee_name | salary | department_id |
|---|---|---|---|
| 3 | 佐藤 | 500000 | 20 |
| 5 | 伊藤 | 450000 | 30 |
この場合、
SELECT AVG(salary)
FROM employee
が副問い合わせです。
副問い合わせの結果である400000を、外側のSQLで利用しています。
3. INを使った副問い合わせ
次に、複数の結果を利用する場合を見てみます。
東京にある部署に所属する社員を取得する
まず、東京にある部署のIDを取得します。
SELECT department_id
FROM department
WHERE location = '東京';
実行結果
| department_id |
|---|
| 10 |
| 30 |
東京にある部署のIDは10と30です。
この結果を使って社員を検索します。
SELECT *
FROM employee
WHERE department_id IN (10, 30);
実行結果
| employee_id | employee_name | salary | department_id |
|---|---|---|---|
| 1 | 田中 | 300000 | 10 |
| 4 | 高橋 | 350000 | 10 |
| 5 | 伊藤 | 450000 | 30 |
この処理を副問い合わせにすると、次のSQLになります。
SELECT *
FROM employee
WHERE department_id IN (
SELECT department_id
FROM department
WHERE location = '東京'
);
実行結果
| employee_id | employee_name | salary | department_id |
|---|---|---|---|
| 1 | 田中 | 300000 | 10 |
| 4 | 高橋 | 350000 | 10 |
| 5 | 伊藤 | 450000 | 30 |
ここでは副問い合わせの結果が10と30の複数行になるため、INを使用しています。
4. EXISTSを使った副問い合わせ
EXISTSは、条件に一致するデータが存在するかを確認するときに使用します。
例えば、
社員が所属している部署を取得する
場合は、次のように書けます。
SELECT *
FROM department d
WHERE EXISTS (
SELECT 1
FROM employee e
WHERE e.department_id = d.department_id
);
実行結果
| department_id | department_name | location |
|---|---|---|
| 10 | 営業部 | 東京 |
| 20 | 開発部 | 大阪 |
| 30 | 総務部 | 東京 |
企画部は結果に含まれていません。
これは、department_id = 40の社員がemployeeテーブルに存在しないためです。
つまりEXISTSは、
・社員が存在する場合は、その部署を取得する。
・社員が存在しない場合は、その部署を取得しない。
という処理になります。
5. FROM句で副問い合わせを使う
副問い合わせはFROM句にも使用できます。
例えば、部署ごとの平均給与を取得します。
SELECT
department_id,
AVG(salary) AS avg_salary
FROM employee
GROUP BY department_id;
実行結果
| department_id | avg_salary |
|---|---|
| 10 | 325000 |
| 20 | 450000 |
| 30 | 450000 |
この結果をさらに検索したい場合、FROM句に副問い合わせを記述できます。
SELECT *
FROM (
SELECT
department_id,
AVG(salary) AS avg_salary
FROM employee
GROUP BY department_id
) AS department_salary
WHERE avg_salary >= 400000;
実行結果
| department_id | avg_salary |
|---|---|
| 20 | 450000 |
| 30 | 450000 |
FROM句の副問い合わせによって、部署ごとの平均給与を一時的なテーブルのように扱っています。
6. 副問い合わせの使い分け
今回紹介した副問い合わせを整理すると、次のようになります。
| 種類 | 用途 |
|---|---|
=など | 1つの値を取得する |
IN | 複数の値を取得する |
EXISTS | データが存在するか確認する |
FROM句 | 検索結果を一時的なテーブルとして利用する |
特に初心者の方は、副問い合わせを見つけたら、まずカッコの中のSQLだけを確認することをおすすめします。
例えば、
SELECT *
FROM employee
WHERE salary > (
SELECT AVG(salary)
FROM employee
);
の場合は、まず、
SELECT AVG(salary)
FROM employee;
を実行すると考えます。
結果は、
400000
です。
その結果を外側のSQLに当てはめると、
SELECT *
FROM employee
WHERE salary > 400000;
となります。
このように、**「副問い合わせを先に実行して、その結果を外側のSQLで利用する」**と考えると理解しやすくなります。
7. まとめ
今回は、すでに存在するテーブルを使って、副問い合わせを実際に実行しました。
副問い合わせは、SQLの中に別のSQLを記述し、その結果を外側のSQLで利用する機能です。
代表的な使い方は以下のとおりです。
-- 1つの値を利用
WHERE salary > (
SELECT AVG(salary)
FROM employee
);
-- 複数の値を利用
WHERE department_id IN (
SELECT department_id
FROM department
WHERE location = '東京'
);
-- 存在を確認
WHERE EXISTS (
SELECT 1
FROM employee e
WHERE e.department_id = d.department_id
);
副問い合わせを理解するポイントは、内側のSQLがどのような結果を返し、その結果を外側のSQLがどのように利用しているかを確認することです。
まずはWHERE句の副問い合わせから実際に実行し、結果を確認しながら覚えていくと理解しやすくなります。
ここまで読んでいただき、ありがとうございます。もしこの記事の技術や考え方に少しでも興味を持っていただけたら、ネクストのエンジニアと気軽に話してみませんか。
- 選考ではありません
- 履歴書不要
- 技術の話が中心
- 所要時間30分程度
- オンラインOK