基础 INNER JOIN
上节课我们聊过 SQL 里有哪些 JOIN 类型。今天我们详细说说 INNER JOIN。
INNER JOIN 是关系型数据库里的一种数据关联方式,它让你从两张表里拿出“匹配”的行,根据你自己设定的条件。 也就是说,INNER JOIN 只会返回两张表交集的部分,其他的都忽略掉。
想象一下,你有两个盒子。一个放着学生的卡片,另一个放着学生报名的课程卡片。你想知道哪些学生报了哪些课。如果没有匹配(比如某个学生啥课都没报),这些数据我们暂时不关心。这种场景就特别适合用 INNER JOIN。
INNER JOIN 的语法
语法其实很直接——你指定两张要关联的表,然后用 ON 关键字写上关联条件。
SELECT 列
FROM 表1 INNER JOIN 表2
ON 表1.字段 = 表2.字段;
表1和表2—— 就是你要关联的两张表。字段—— 就是用来匹配的列。ON后面的条件就是两张表行怎么对应的规则。
INNER JOIN 的使用例子
下面的例子我们用两张表:
表 students —— 学生信息
| student_id | name | age |
|---|---|---|
| 1 | Otto | 20 |
| 2 | Anna | 22 |
| 3 | Peter | 19 |
| 4 | Dia | 21 |
表 enrollments —— 课程报名信息
| enrollment_id | student_id | course_id |
|---|---|---|
| 101 | 1 | 501 |
| 102 | 2 | 502 |
| 103 | 2 | 503 |
| 104 | 3 | 504 |
注意,学生 Dia(student_id = 4)没有报任何课程。
例子 1:查学生和他们的课程
我们想知道哪些学生报了哪些课。这就是 INNER JOIN 的典型用法。我们只关心 students 和 enrollments 这两张表里 student_id 有匹配的数据。
SELECT students.name, enrollments.course_id
FROM students INNER JOIN enrollments
ON students.student_id = enrollments.student_id;
结果:
| name | course_id |
|---|---|
| Otto | 501 |
| Anna | 502 |
| Anna | 503 |
| Peter | 504 |
你看到了吧?INNER JOIN 只返回了那些报了课程的学生。Dia 没报课,所以没出现在结果里。
例子 2:查订单和客户
再来看个例子。假如我们有 orders(订单)和 customers(客户)两张表。我们想查所有订单和客户的名字。
表 orders
| order_id | customer_id | amount |
|---|---|---|
| 1 | 101 | 500 |
| 2 | 102 | 300 |
| 3 | 103 | 700 |
表 customers
| customer_id | name |
|---|---|
| 101 | Otto |
| 102 | Anna |
| 104 | Peter |
任务:我们要把 orders 和 customers 按 customer_id 关联,只返回有对应客户的订单。
SELECT orders.order_id, customers.name, orders.amount
FROM orders INNER JOIN customers
ON orders.customer_id = customers.customer_id;
结果:
| order_id | name | amount |
|---|---|---|
| 1 | Otto | 500 |
| 2 | Anna | 300 |
注意,order_id = 3 的订单没出现在结果里,因为 customer_id = 103 的客户在 customers 表里不存在。
INNER JOIN 怎么帮你关联表(以及可能踩的坑)
INNER JOIN 是你做任何关系型数据库项目时最常用的工具之一。就像工具箱里的扳手:你可以不用,但会很难搞定需求。比如:
- 做报表时,需要把多张表的数据合起来。
- 做分析时,要把事实表和维度表连起来(比如销售和客户)。
- 整合外部系统的数据。
新手最常犯的错就是忘了写 ON 或者条件写错。如果你没写对条件,结果就不是你想要的,而是两张表的笛卡尔积——可能会有成千上万条没意义的数据。
错误例子:
这个例子里没有写关联条件,所以 SQL 会把两张表的每一行都组合一遍(基本就是灾难):
SELECT students.name, enrollments.course_id
FROM students, enrollments; -- 错误:没有写关联条件!
结果会一团乱:每个 students 的行都和每个 enrollments 的行拼在一起。
GO TO FULL VERSION