今日は一番フレンドリーなデータ結合方法、FULL OUTER JOINについてやっていくよ。これは、ペアがなくてもみんな結果に入れる結合なんだ。
FULL OUTER JOINは、全ての行を両方のテーブルから返してくれるJOINの一種。もし片方のテーブルに対応する行がなかったら、その部分はNULLで埋めてくれる。たとえば、2つの違うパーティーに来た人を全部リストアップする感じ。どっちかだけ来た人もちゃんとカウントされるよ。
イメージ的にはこんな感じ:
テーブルA テーブルB
+----+----------+ +----+----------+
| id | 名前 | | id | コース |
+----+----------+ +----+----------+
| 1 | Alice | | 2 | Math |
| 2 | Bob | | 3 | Physics |
| 4 | Charlie | | 5 | History |
+----+----------+ +----+----------+
FULL OUTER JOINの結果:
+----+----------+----------+
| id | 名前 | コース |
+----+----------+----------+
| 1 | Alice | NULL |
| 2 | Bob | Math |
| 3 | NULL | Physics |
| 4 | Charlie | NULL |
| 5 | NULL | History |
+----+----------+----------+
対応する行がなくても、その行は残るけど、足りないカラムはNULLで埋まるよ。
FULL OUTER JOINの構文
構文はシンプルだけど、めっちゃパワフル:
SELECT
カラムたち
FROM
テーブル1
FULL OUTER JOIN
テーブル2
ON テーブル1.共通カラム = テーブル2.共通カラム;
ここで大事なのはFULL OUTER JOIN。これでPostgreSQLは両方のテーブルの全ての行を持ってきてくれる。ONの条件でペアがなかったら、その部分はNULLになるよ。
使い方の例
おなじみのuniversityデータベースのstudentsとenrollmentsテーブルを使って、実際の例を見てみよう。
例1: 全ての学生とコースのリスト
2つのテーブルがあるとする:
テーブル students:
| student_id | 名前 |
|---|---|
| 1 | Alice |
| 2 | Bob |
| 3 | Charlie |
テーブル enrollments:
| enrollment_id | student_id | コース |
|---|---|---|
| 101 | 1 | Math |
| 102 | 2 | Physics |
| 103 | 4 | History |
やりたいことは、どのコースにも登録してない学生も、学生がいないコースも含めて、全員・全部のリストを作ること。
クエリはこれ:
SELECT
s.student_id,
s.名前,
e.コース
FROM
students s
FULL OUTER JOIN
enrollments e
ON
s.student_id = e.student_id;
結果:
| student_id | 名前 | コース |
|---|---|---|
| 1 | Alice | Math |
| 2 | Bob | Physics |
| 3 | Charlie | NULL |
| NULL | NULL | History |
見ての通り、全ての学生と全てのコースが結果に入ってる。Charlieはコースに登録してないからcourseがNULL。Historyは学生がいないからstudent_idと名前がNULLだよ。
例2: 売上と商品を分析する
今度はお店を考えてみよう。2つのテーブルがある:
テーブル products:
| product_id | 名前 |
|---|---|
| 1 | Laptop |
| 2 | Smartphone |
| 3 | Printer |
テーブル sales:
| sale_id | product_id | 数量 |
|---|---|---|
| 101 | 1 | 5 |
| 102 | 3 | 2 |
| 103 | 4 | 10 |
売れてない商品も、product_idが変な売上も、全部リストにしたい。
クエリ:
SELECT
p.product_id,
p.名前 AS product_name,
s.数量
FROM
products p
FULL OUTER JOIN
sales s
ON
p.product_id = s.product_id;
結果:
| product_id | product_name | 数量 |
|---|---|---|
| 1 | Laptop | 5 |
| 2 | Smartphone | NULL |
| 3 | Printer | 2 |
| NULL | NULL | 10 |
ここで、Smartphoneは売れてない(数量 = NULL)、product_id = 4の売上はどの商品にも対応してないのがわかるね。
実践課題
departmentsとemployeesテーブルでクエリを書いてみよう:
テーブル departments:
| department_id | 部署名 |
|---|---|
| 1 | HR |
| 2 | IT |
| 3 | Marketing |
テーブル employees:
| employee_id | department_id | 名前 |
|---|---|---|
| 101 | 1 | Alice |
| 102 | 2 | Bob |
| 103 | 4 | Charlie |
FULL OUTER JOINで全ての部署と社員のリストを作って、足りない部分はNULLで埋めてみて!
NULL値の扱い方
NULL値の問題は、FULL OUTER JOINを使うと避けられない。実際の現場だと、NULLをもっと意味のある値に置き換えたいこともあるよね。PostgreSQLならCOALESCE()関数でできる!
例:
SELECT
COALESCE(s.名前, '学生なし') AS student_name,
COALESCE(e.コース, 'コースなし') AS course_name
FROM
students s
FULL OUTER JOIN
enrollments e
ON
s.student_id = e.student_id;
結果:
| student_name | course_name |
|---|---|
| Alice | Math |
| Bob | Physics |
| Charlie | コースなし |
| 学生なし | History |
これでNULLの代わりに意味のある値が表示されて、レポートも読みやすくなるよ。
FULL OUTER JOINを使うタイミング
FULL OUTER JOINは、全てのデータを両方のテーブルから見たいときに便利。例えば:
- 売上と商品のレポート ― 売れた商品も売れてない商品も全部見たいとき。
- 学生とコースの分析 ― 抜けてるデータがないかチェックしたいとき。
- リストの比較 ― 2つのデータセットの違いを見つけたいとき。
このレクチャーでFULL OUTER JOINのイメージがつかめたら嬉しい!これからもっと複雑なJOINやデータ処理の世界が待ってるよ!
GO TO FULL VERSION