今天我们来搞懂最“包容”的数据合并方式——FULL OUTER JOIN。这种合并,谁都能进结果集,就算没有配对也没关系。
FULL OUTER JOIN 就是那种能把所有行都返回的合并方式。不管某一行在另一张表里有没有对应的,没找到的地方就用 NULL 补上。就像统计两场派对所有来的人:哪怕有人只去了其中一场,也会被统计进去。
用图来理解大概是这样:
表 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 |
+----+----------+----------+
没有匹配的行也会保留,不过缺的列会用 NULL 填上。
FULL OUTER JOIN 的语法
语法很简单,但功能很强大:
SELECT
列名
FROM
表1
FULL OUTER JOIN
表2
ON 表1.公共列 = 表2.公共列;
关键就在 FULL OUTER JOIN,它让 PostgreSQL 把两张表的所有行都拿出来。只要 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 |
我们的目标是:列出所有学生和课程,包括没选课的学生和没人选的课程。
SQL 语句如下:
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 不对的销售。
SQL 语句:
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 有了直观的认识。接下来你就可以探索更复杂的数据合并和处理啦!
GO TO FULL VERSION