SQLのJOINを完全ガイド!初心者でもわかるテーブルの結合方法
新人
「SQLで複数のテーブルからデータを取得する方法ってありますか?」
先輩
「それならJOINを使うといいよ!JOINを使うと、異なるテーブルを組み合わせてデータを取得できるんだ。」
新人
「JOINって何ですか?」
先輩
「JOINは、複数のテーブルを結合して、必要なデータを一緒に取得するためのSQL構文だよ。実際にテーブルを使って説明するね!」
1. JOINとは?
JOINとは、複数のテーブルを結合してデータを取得するSQLの機能です。
例えば、以下のような2つのテーブルがあるとします。
1. employees(社員テーブル)
| employee_id | name | department_id |
|---|---|---|
| 1 | 田中 太郎 | 101 |
| 2 | 佐藤 花子 | 102 |
| 3 | 鈴木 一郎 | 101 |
| 4 | 高橋 直子 | 103 |
2. departments(部署テーブル)
| department_id | department_name |
|---|---|
| 101 | 営業 |
| 102 | マーケティング |
| 103 | 人事 |
この2つのテーブルを結合し、社員とその部署名を一緒に取得することができます。
2. INNER JOINの使い方
INNER JOINは、両方のテーブルに一致するデータだけを取得するJOINの方法です。
1. INNER JOINの基本構文
SELECT employees.employee_id, employees.name, departments.department_name
FROM employees
INNER JOIN departments ON employees.department_id = departments.department_id;
このSQLを実行すると、employeesテーブルとdepartmentsテーブルの共通するdepartment_idを基にデータを結合し、社員名と部署名を取得できます。
2. INNER JOINの実行結果
| employee_id | name | department_name |
|---|---|---|
| 1 | 田中 太郎 | 営業 |
| 2 | 佐藤 花子 | マーケティング |
| 3 | 鈴木 一郎 | 営業 |
| 4 | 高橋 直子 | 人事 |
このように、INNER JOINを使うと、複数のテーブルを結合し、関連するデータを取得できます。
3. INNER JOINを使うメリット
- データの整合性を維持できる - 一致するデータのみを取得できる
- 複数のテーブルをまとめて扱える - 1つのSQLで関連データを取得可能
- パフォーマンスが良い - 不要なデータを取得しないため効率的
4. WHERE句との違い
INNER JOINとWHEREを使ってテーブルを結合することもできますが、JOINの方が読みやすく、最適化されやすいです。
WHERE句を使った例:
SELECT employees.employee_id, employees.name, departments.department_name
FROM employees, departments
WHERE employees.department_id = departments.department_id;
この方法でもJOINと同じ結果を得られますが、現在のSQL標準ではINNER JOINの方が推奨されています。
次のセクションでは、LEFT JOINやRIGHT JOINを使った結合方法について解説します。
4. LEFT JOINとRIGHT JOINの違い(片側にないデータの扱い)
INNER JOINでは、両方のテーブルに共通するデータだけが取得されます。しかし、LEFT JOINやRIGHT JOINを使用すると、一方のテーブルにしかないデータも取得できます。
1. LEFT JOIN(左外部結合)
LEFT JOINは、左側のテーブルのすべてのデータを取得し、右側のテーブルに一致するデータがあれば結合します。一致しない場合はNULLが返されます。
SELECT employees.employee_id, employees.name, departments.department_name
FROM employees
LEFT JOIN departments ON employees.department_id = departments.department_id;
2. LEFT JOINの実行結果
例えば、以下のデータがあった場合:
| employee_id | name | department_id |
|---|---|---|
| 1 | 田中 太郎 | 101 |
| 2 | 佐藤 花子 | 102 |
| 3 | 鈴木 一郎 | 101 |
| 4 | 高橋 直子 | NULL |
LEFT JOINの結果:
| employee_id | name | department_name |
|---|---|---|
| 1 | 田中 太郎 | 営業 |
| 2 | 佐藤 花子 | マーケティング |
| 3 | 鈴木 一郎 | 営業 |
| 4 | 高橋 直子 | NULL |
3. RIGHT JOIN(右外部結合)
RIGHT JOINは、右側のテーブルのすべてのデータを取得し、左側のテーブルに一致するデータがあれば結合します。
SELECT employees.employee_id, employees.name, departments.department_name
FROM employees
RIGHT JOIN departments ON employees.department_id = departments.department_id;
4. RIGHT JOINの実行結果
以下のような結果になります:
| employee_id | name | department_name |
|---|---|---|
| 1 | 田中 太郎 | 営業 |
| 3 | 鈴木 一郎 | 営業 |
| 2 | 佐藤 花子 | マーケティング |
| NULL | NULL | 人事 |
このように、LEFT JOINとRIGHT JOINを使うことで、片方のテーブルにしかないデータも取得できます。
5. CROSS JOINとは?(全組み合わせの結合)
CROSS JOINは、両方のテーブルのすべての組み合わせ(直積)を取得するJOINです。
1. CROSS JOINの基本構文
SELECT employees.name, departments.department_name
FROM employees
CROSS JOIN departments;
2. CROSS JOINの実行結果
例えば、employeesテーブルに4人、departmentsテーブルに3つの部署がある場合、結果は4×3=12行になります。
| name | department_name |
|---|---|
| 田中 太郎 | 営業 |
| 田中 太郎 | マーケティング |
| 田中 太郎 | 人事 |
| 佐藤 花子 | 営業 |
| 佐藤 花子 | マーケティング |
| 佐藤 花子 | 人事 |
| 鈴木 一郎 | 営業 |
| 鈴木 一郎 | マーケティング |
| 鈴木 一郎 | 人事 |
| 高橋 直子 | 営業 |
| 高橋 直子 | マーケティング |
| 高橋 直子 | 人事 |
このように、CROSS JOINを使用すると、すべての組み合わせのデータを取得できます。
6. JOINを利用したデータ取得の最適化
JOINを使用すると、データ取得の効率が上がりますが、最適化しないとパフォーマンスが低下することがあります。
1. インデックスを活用する
JOINで結合するカラムにはINDEXを設定すると、検索速度が向上します。
CREATE INDEX idx_department_id ON employees(department_id);
2. 不要なデータの取得を避ける
不要なカラムを取得すると、処理が重くなるので、必要なカラムだけを指定するようにしましょう。
SELECT employees.name, departments.department_name
FROM employees
INNER JOIN departments ON employees.department_id = departments.department_id;
このように、JOINを適切に活用し、パフォーマンスを最適化しましょう。
7. FULL OUTER JOINとは?(両方のテーブルのデータを取得)
FULL OUTER JOINは、両方のテーブルのデータをすべて取得する結合方法です。
INNER JOINは一致するデータのみを取得し、LEFT JOINやRIGHT JOINは片方のテーブルに一致しないデータも取得できますが、FULL OUTER JOINは両方のテーブルのすべてのデータを取得し、一致しない部分にはNULLが入ります。
1. FULL OUTER JOINの基本構文
SELECT employees.employee_id, employees.name, departments.department_name
FROM employees
FULL OUTER JOIN departments ON employees.department_id = departments.department_id;
2. FULL OUTER JOINの実行結果
例えば、以下の2つのテーブルがある場合:
employees(社員テーブル)
| employee_id | name | department_id |
|---|---|---|
| 1 | 田中 太郎 | 101 |
| 2 | 佐藤 花子 | 102 |
| 3 | 鈴木 一郎 | NULL |
departments(部署テーブル)
| department_id | department_name |
|---|---|
| 101 | 営業 |
| 102 | マーケティング |
| 103 | 人事 |
この2つのテーブルをFULL OUTER JOINで結合すると、以下のようになります。
FULL OUTER JOINの結果
| employee_id | name | department_name |
|---|---|---|
| 1 | 田中 太郎 | 営業 |
| 2 | 佐藤 花子 | マーケティング |
| 3 | 鈴木 一郎 | NULL |
| NULL | NULL | 人事 |
このように、FULL OUTER JOINを使うと、両方のテーブルにあるデータをすべて取得し、一致しない部分にはNULLが入ります。
8. JOINとサブクエリの違い(どちらを使うべきか)
SQLでは、JOINの代わりにサブクエリを使用することもできます。しかし、どちらを選ぶべきかはケースによります。
1. JOINを使う場合
複数のテーブルからデータを効率的に取得したい場合は、JOINを使うのが適切です。
SELECT employees.name, departments.department_name
FROM employees
INNER JOIN departments ON employees.department_id = departments.department_id;
この方法はパフォーマンスが高く、データの関連を明確に保つことができます。
2. サブクエリを使う場合
一時的な集計結果を取得したい場合や、条件付きでデータを取得したい場合はサブクエリを使うと便利です。
SELECT name,
(SELECT department_name FROM departments
WHERE departments.department_id = employees.department_id) AS department_name
FROM employees;
この方法はコードが短くなることがありますが、大量のデータを扱う場合はJOINの方がパフォーマンスが良いことが多いです。
9. 実践!JOINを活用した複雑なデータ取得テクニック
最後に、JOINを活用した実践的なデータ取得の例を紹介します。
1. 3つ以上のテーブルを結合する
以下のように、3つのテーブルを結合してデータを取得することも可能です。
SELECT employees.name, departments.department_name, salaries.salary
FROM employees
INNER JOIN departments ON employees.department_id = departments.department_id
INNER JOIN salaries ON employees.employee_id = salaries.employee_id;
2. 集約関数とJOINを組み合わせる
JOINを使用すると、複数のテーブルを組み合わせて集計することもできます。
SELECT departments.department_name, AVG(salaries.salary) AS average_salary
FROM employees
INNER JOIN departments ON employees.department_id = departments.department_id
INNER JOIN salaries ON employees.employee_id = salaries.employee_id
GROUP BY departments.department_name;
このSQLは、部署ごとの平均給与を計算するクエリです。
3. JOINと条件を組み合わせた検索
SELECT employees.name, departments.department_name
FROM employees
INNER JOIN departments ON employees.department_id = departments.department_id
WHERE departments.department_name = '営業';
このSQLでは、「営業」部署の社員だけを取得しています。
このように、JOINを活用することで、複雑なデータを効率的に取得することができます。