0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

結合の基礎

Posted at

準備するテーブル

例として、Employees(従業員)テーブルと**Departments(部署)テーブル**を用意します。

  • 従業員の中には、まだ部署に配属されていない人(田中さん)がいます。
  • 部署の中には、まだ従業員が一人もいない部署(人事部)があります。

Employees テーブル (A)

EmployeeID EmployeeName DepartmentID
1 佐藤 101
2 鈴木 102
3 高橋 103
4 田中 NULL

Departments テーブル (B)

DepartmentID DepartmentName
101 営業部
102 開発部
104 人事部

1. INNER JOIN (内部結合)

両方のテーブルに共通して存在するデータのみを結合します。

SQL

SELECT *
FROM Employees AS A
INNER JOIN Departments AS B ON A.DepartmentID = B.DepartmentID;

実行結果

EmployeeID EmployeeName DepartmentID DepartmentID DepartmentName
1 佐藤 101 101 営業部
2 鈴木 102 102 開発部

解説
EmployeesテーブルとDepartmentsテーブルの両方に存在するDepartmentID(101と102)を持つ行だけが表示されます。部署IDが103の高橋さん、NULLの田中さん、そして従業員がいない人事部(104)は結果に含まれません。

image.png


2. FULL OUTER JOIN (完全外部結合)

両方のテーブルのすべての行を結合します。片方にしか存在しないデータの場合、もう片方のカラムはNULLになります。

SQL

SELECT *
FROM Employees AS A
FULL OUTER JOIN Departments AS B ON A.DepartmentID = B.DepartmentID;

実行結果

EmployeeID EmployeeName DepartmentID DepartmentID DepartmentName
1 佐藤 101 101 営業部
2 鈴木 102 102 開発部
3 高橋 103 NULL NULL
4 田中 NULL NULL NULL
NULL NULL NULL 104 人事部

解説
すべての従業員とすべての部署が表示されます。

  • 高橋さん(103)と田中さん(NULL)は、対応する部署がないため、部署名のカラムがNULLになります。
  • 人事部(104)は、対応する従業員がいないため、従業員情報のカラムがNULLになります。

image.png


3. FULL OUTER JOIN ... WHERE ... IS NULL (片方にしかない)

FULL OUTER JOINの結果から、両方に共通する部分(INNER JOINの結果)を除外します。どちらか一方のテーブルにしか存在しないデータのみを抽出します。

SQL

SELECT *
FROM Employees AS A
FULL OUTER JOIN Departments AS B ON A.DepartmentID = B.DepartmentID
WHERE A.EmployeeID IS NULL OR B.DepartmentID IS NULL;

実行結果

EmployeeID EmployeeName DepartmentID DepartmentID DepartmentName
3 高橋 103 NULL NULL
4 田中 NULL NULL NULL
NULL NULL NULL 104 人事部

解説
部署が存在しない従業員(高橋さん、田中さん)と、従業員がいない部署(人事部)のみが表示されます。
image.png


4. LEFT JOIN (左外部結合)

左側のテーブル(Employees)のすべての行を基準に、右側のテーブル(Departments)を結合します。右側に一致するデータがない場合はNULLになります。

SQL

SELECT *
FROM Employees AS A
LEFT JOIN Departments AS B ON A.DepartmentID = B.DepartmentID;

実行結果

EmployeeID EmployeeName DepartmentID DepartmentID DepartmentName
1 佐藤 101 101 営業部
2 鈴木 102 102 開発部
3 高橋 103 NULL NULL
4 田中 NULL NULL NULL

解説
Employeesテーブルの全従業員が表示されます。対応する部署がない高橋さんと田中さんは、部署関連のカラムがNULLになります。Departmentsテーブルにしか存在しない人事部(104)は結果に含まれません。

image.png


5. LEFT JOIN ... WHERE ... IS NULL (左側にしかない)

左側のテーブル(Employees)にのみ存在し、右側のテーブル(Departments)には対応するデータがない行を抽出します。

SQL

SELECT *
FROM Employees AS A
LEFT JOIN Departments AS B ON A.DepartmentID = B.DepartmentID
WHERE B.DepartmentID IS NULL;

実行結果

EmployeeID EmployeeName DepartmentID DepartmentID DepartmentName
3 高橋 103 NULL NULL
4 田中 NULL NULL NULL

解説
部署に所属していない従業員(高橋さん、田中さん)だけが表示されます。

image.png


6. RIGHT JOIN (右外部結合)

右側のテーブル(Departments)のすべての行を基準に、左側のテーブル(Employees)を結合します。LEFT JOINの逆です。

SQL

SELECT *
FROM Employees AS A
RIGHT JOIN Departments AS B ON A.DepartmentID = B.DepartmentID;

実行結果

EmployeeID EmployeeName DepartmentID DepartmentID DepartmentName
1 佐藤 101 101 営業部
2 鈴木 102 102 開発部
NULL NULL NULL 104 人事部

解説
Departmentsテーブルの全部署が表示されます。対応する従業員がいない人事部(104)は、従業員情報のカラムがNULLになります。Employeesテーブルにしか存在しない従業員(高橋さん、田中さん)は結果に含まれません。

image.png


7. RIGHT JOIN ... WHERE ... IS NULL (右側にしかない)

右側のテーブル(Departments)にのみ存在し、左側のテーブル(Employees)には対応するデータがない行を抽出します。

SQL

SELECT *
FROM Employees AS A
RIGHT JOIN Departments AS B ON A.DepartmentID = B.DepartmentID
WHERE A.EmployeeID IS NULL;

実行結果

EmployeeID EmployeeName DepartmentID DepartmentID DepartmentName
NULL NULL NULL 104 人事部

解説
まだ従業員が一人も配属されていない部署(人事部)だけが表示されます。

image.png


実際に「へんてこ」な結合結果を見てみよう

2つのテーブルでLEFT JOINを実行すると、何が起こるか見てみましょう。

学生テーブル

学生ID せいべつ
1 0
2 1
3 1
4 1

部活テーブル

部活ID せいべつ
1 1
2 1
3 1
4 1

クエリ

SELECT *
FROM 学生
LEFT JOIN 部活 ON 学生.せいべつ = 部活.せいべつ;

実行結果

学生ID 学生.せいべつ 部活ID 部活.せいべつ
1 0 NULL NULL
2 1 1 1
2 1 2 1
2 1 3 1
2 1 4 1
3 1 1 1
3 1 2 1
3 1 3 1
3 1 4 1
4 1 1 1
4 1 2 1
4 1 3 1
4 1 4 1

何が起きたか

  • 学生ID 1 (せいべつ 0) は、部活テーブルにマッチする行がないため、相手側がNULLの1行になります。これはLEFT JOINの正常な動きです。
  • 学生ID 2 (せいべつ 1) は、部活テーブルの4つの行すべてにマッチします。そのため、学生ID 2 の行が4つに増殖してしまいました。
  • 学生ID 34 も同様に4つずつに増殖します。

結果として、元のテーブルは4行ずつだったのに、合計13行というとんでもない結果になってしまいました。これが「へんてこ」の正体です。


まとめ

  • 文法上のルール: データ型が合っていれば、どんなカラムでも結合できる。
  • 実用上のルール(ベストプラクティス): 意味のあるデータ関係を作るためには、**主キー(Primary Key)外部キー(Foreign Key)**のような、一意性のある、あるいは親子関係を示すカラムで結合するのが普通です。

「一意性がないとダメな気がする」という感覚が、データ分析やシステム開発において、意図しない結果を避けるための非常に重要な感覚と言えます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?