JOIN 多表联结
INNER / LEFT JOIN,何时需要多表。
JOIN 多表联结
这一课你将能做到
- 用 INNER JOIN 把 2~4 张表按外键关系拼成一张宽结果
- 用 LEFT JOIN + IS NULL 找出「没有匹配」的行(没有课时的课程、没学过习的学生)
- 说清 ON 与 WHERE 的区别,避开 LEFT JOIN 被 WHERE「吃掉」的经典坑
前置:第一课建库脚本已跑;本课查询会用到第 6 课会改动数据,若你在前面课删过课时,先回第一课重跑脚本复原数据,保证输出一致。
为什么要学
第一课就说了:关系型数据库的纪律是「同一事实只存一次」。代价是数据拆在多张表——study_record 里只有 student_id 和 lesson_id 两个数字,单表查询根本看不出「谁、学了哪节课、考了多少分」。JOIN 就是把这些拆开的表按外键拼宽的语言结构,是关系型数据库相对 Excel 的核心能力,也是面试必考。
先建立图像
JOIN 按「拼接条件」把两张表的行配对。配得上就拼到一起,配不上 Inner 直接丢、Left 用 NULL 补位:
INNER JOIN course ⋈ lesson LEFT JOIN course ⋈ lesson
(只保留两边都配上的) (左表全保留,右表缺位补 NULL)
course lesson course lesson
1 ●─────────● 1 1 ●─────────● 1
2 ●─────────● 2 2 ●─────────● 2
3 ●─────────● 3 3 ●─────────● 3
7 ○(没课时,被丢掉) 7 ○──→ NULL(保留,右侧补空)
本练习库的关系图(记住它,后面 6 课都用):
student 1 ──< study_record >── 1 lesson >── 1 course
│
student 1 ──< pay_order >──────────────┘(订单直接挂课程)
跟着做
步骤 1:感受「单表查不出人话」
SELECT student_id, lesson_id, score FROM study_record LIMIT 5;
-- 1 6 92 1 7 88 1 1 95 …… 谁是 1?6 是哪节课?不知道
数字 id 只对机器有意义,人需要名字和标题——这就是 JOIN 存在的理由。
步骤 2:两表 INNER JOIN
SELECT r.id, l.title, r.score
FROM study_record r
JOIN lesson l ON r.lesson_id = l.id;
-- 17 行:每条学习记录配上了课时标题
读法:从 study_record(别名 r)出发,拿 r.lesson_id 去匹配 lesson.id,配上的行拼在一起。JOIN 是 INNER JOIN 的简写。
步骤 3:三表、四表联结(真实接口长这样)
SELECT s.name, c.title AS course_title, l.title AS lesson_title, r.score
FROM study_record r
JOIN student s ON r.student_id = s.id
JOIN lesson l ON r.lesson_id = l.id
JOIN course c ON l.course_id = c.id
WHERE r.completed = 1
ORDER BY r.score DESC
LIMIT 5;
-- 阿珍 98(SQL 是什么)/ 老陈 95(环境搭建)/ 阿珍 95(SELECT 基本查询)
-- 老周 92(EXPLAIN 详解)/ 老陈 92(变量与数据类型)
一条语句串了 4 张表,这就是「学习记录页」接口背后的查询原型。