想象一下你有两张表:一个学生名单,还有一个他们选课的表。不是每个学生都选了课,你想看到所有学生的完整列表,包括那些还没选课的。用 INNER JOIN 只能看到已经选课的学生,那没选课的咋办?这时候就要用 LEFT JOIN 了。
LEFT JOIN 会返回左表的所有行(就是你查询里第一个写的表),还有右表里能匹配的行。如果右表没匹配,右表的列就会是 NULL。
LEFT JOIN 的语法:
SELECT
表1.列1,
表1.列2,
表2.列1,
表2.列2
FROM
表1 LEFT JOIN 表2
ON
表1.公共列 = 表2.公共列;
表1—— 这是“左表”。表2—— 这是“右表”。公共列—— 用来关联的公共字段。
举个简单例子
如果 students 表长这样:
| student_id | name |
|---|---|
| 1 | Otto |
| 2 | Anna |
| 3 | Peter |
而 enrollments 表长这样:
| enrollment_id | student_id | course |
|---|---|---|
| 1 | 1 | 数学 |
| 2 | 1 | 物理 |
| 3 | 2 | 生物 |
那这个查询:
SELECT
students.name,
enrollments.course
FROM
students LEFT JOIN enrollments
ON
students.student_id = enrollments.student_id;
会查出:
| name | course |
|---|---|
| Otto | 数学 |
| Otto | 物理 |
| Anna | 生物 |
| Peter | NULL |
你看,结果里所有学生都在,连 Peter 这种还没选课的也有。Peter 的 course 列就是 NULL。
LEFT JOIN 的使用例子
例子1:查所有学生和他们的课程
比如说,我们要查所有学生和他们选的课,如果没选课也要显示出来。
还是这个查询:
SELECT
students.name,
enrollments.course
FROM
students LEFT JOIN enrollments
ON
students.student_id = enrollments.student_id;
结果:
| name | course |
|---|---|
| Otto | 数学 |
| Otto | 物理 |
| Anna | 生物 |
| Peter | NULL |
这就是 LEFT JOIN 的经典用法。
例子2:查商品和它们的销量
假设你有两张表:
products 表,存所有商品:
| product_id | product_name |
|---|---|
| 1 | 智能手机 |
| 2 | 平板 |
| 3 | 笔记本 |
sales 表,存销量数据:
| sale_id | product_id | quantity |
|---|---|---|
| 1 | 1 | 5 |
| 2 | 1 | 3 |
| 3 | 2 | 2 |
现在你想查所有商品和它们的销量,包括那些还没卖出去的。
SELECT
products.product_name,
SUM(sales.quantity) AS total_sold
FROM
products LEFT JOIN sales
ON
products.product_id = sales.product_id
GROUP BY
products.product_name;
结果:
| product_name | total_sold |
|---|---|
| 智能手机 | 8 |
| 平板 | 2 |
| 笔记本 | NULL |
用 LEFT JOIN 时的注意点和坑
一定要 NULL 吗?
有时候 LEFT JOIN 会给你加上 NULL,但你其实想显示点别的。这时候可以用 COALESCE() 函数把 NULL 换成你想要的值。
SELECT
students.name,
COALESCE(enrollments.course, '未选课程') AS course
FROM
students LEFT JOIN enrollments
ON
students.student_id = enrollments.student_id;
结果:
| name | course |
|---|---|
| Otto | 数学 |
| Otto | 物理 |
| Anna | 生物 |
| Peter | 未选课程 |
多余的重复
如果右表有重复数据,查出来的结果可能比你想的多。要注意你查的数据,真不想要重复就用 DISTINCT。
GO TO FULL VERSION