今天我們要來搞懂最佛心的資料合併方式 —— FULL OUTER JOIN。這種 join 超包容,大家都能進結果集,就算沒配對到也沒關係。
FULL OUTER JOIN 就是那種會把 所有 row 都抓出來的 join。只要有一邊沒對到,缺的欄位就會用 NULL 補上。這就像你要統計兩場 party 的所有來賓:就算有人只去了一場,他還是會被算進來。
用圖來看大概長這樣:
表格 A 表格 B
+----+----------+ +----+----------+
| id | name | | id | course |
+----+----------+ +----+----------+
| 1 | Alice | | 2 | Math |
| 2 | Bob | | 3 | Physics |
| 4 | Charlie | | 5 | History |
+----+----------+ +----+----------+
FULL OUTER JOIN 結果:
+----+----------+----------+
| id | name | course |
+----+----------+----------+
| 1 | Alice | NULL |
| 2 | Bob | Math |
| 3 | NULL | Physics |
| 4 | Charlie | NULL |
| 5 | NULL | History |
+----+----------+----------+
沒有配對到的 row 也會留下來,缺的欄位就會是 NULL。
FULL OUTER JOIN 語法
語法很簡單,但功能超強:
SELECT
欄位們
FROM
表格1
FULL OUTER JOIN
表格2
ON 表格1.共用欄位 = 表格2.共用欄位;
重點就是 FULL OUTER JOIN,這會讓 PostgreSQL 把 兩張表的所有 row 都抓出來。只要 ON 條件沒配對到,缺的地方就會是 NULL。
使用範例
來看幾個實際例子,用大家熟的 university 資料庫,裡面有 students 跟 enrollments 兩張表。
範例 1:所有學生和課程的清單
假設我們有兩張表:
表格 students:
| student_id | name |
|---|---|
| 1 | Alice |
| 2 | Bob |
| 3 | Charlie |
表格 enrollments:
| enrollment_id | student_id | course |
|---|---|---|
| 101 | 1 | Math |
| 102 | 2 | Physics |
| 103 | 4 | History |
我們的目標是要列出所有學生和課程,就算學生沒修課或課程沒人修也要出現。
查詢語句如下:
SELECT
s.student_id,
s.name,
e.course
FROM
students s
FULL OUTER JOIN
enrollments e
ON
s.student_id = e.student_id;
查詢結果:
| student_id | name | course |
|---|---|---|
| 1 | Alice | Math |
| 2 | Bob | Physics |
| 3 | Charlie | NULL |
| NULL | NULL | History |
你看,所有學生和課程都出現了。Charlie 沒修課,所以 course 是 NULL。History 這門課沒學生,所以 student_id 跟 name 都是 NULL。
範例 2:銷售和商品分析
換個情境,假設我們有一間店。有兩張表:
表格 products:
| product_id | name |
|---|---|
| 1 | Laptop |
| 2 | Smartphone |
| 3 | Printer |
表格 sales:
| sale_id | product_id | quantity |
|---|---|---|
| 101 | 1 | 5 |
| 102 | 3 | 2 |
| 103 | 4 | 10 |
我們想要看到所有商品和銷售紀錄,就算商品沒賣出或有奇怪的 product_id 也要顯示。
查詢語句:
SELECT
p.product_id,
p.name AS product_name,
s.quantity
FROM
products p
FULL OUTER JOIN
sales s
ON
p.product_id = s.product_id;
查詢結果:
| product_id | product_name | quantity |
|---|---|---|
| 1 | Laptop | 5 |
| 2 | Smartphone | NULL |
| 3 | Printer | 2 |
| NULL | NULL | 10 |
這裡你會發現 Smartphone 沒賣出(quantity = NULL),而 product_id = 4 的銷售紀錄找不到對應商品。
實作練習
來試試看,請你幫 departments 跟 employees 兩張表寫個查詢:
表格 departments:
| department_id | department_name |
|---|---|
| 1 | HR |
| 2 | IT |
| 3 | Marketing |
表格 employees:
| employee_id | department_id | name |
|---|---|---|
| 101 | 1 | Alice |
| 102 | 2 | Bob |
| 103 | 4 | Charlie |
請寫一個 FULL OUTER JOIN,把所有部門和員工都列出來,缺的地方用 NULL 補。
怎麼處理 NULL 值
NULL 值是用 FULL OUTER JOIN 必然會遇到的問題。有時候你會想把 NULL 換成比較有意義的內容。在 PostgreSQL 裡可以用 COALESCE() 這個函數。
範例:
SELECT
COALESCE(s.name, '沒有學生') AS student_name,
COALESCE(e.course, '沒有課程') 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 很適合你想要看到 所有資料,就算沒完全對應也要顯示的時候。舉例:
- 銷售和商品報表 —— 想同時看到有賣跟沒賣的商品。
- 學生和課程分析 —— 想檢查有沒有漏掉的資料。
- 比對清單 —— 比如要找出兩份資料集的差異。
希望這堂課讓你對 FULL OUTER JOIN 有個清楚的概念。接下來你就可以進入更進階的 join 跟資料處理世界啦!
GO TO FULL VERSION