MySQL中IN和EXISTS用于子查询过滤。IN判断值是否在列表中,EXISTS判断子查询是否存在关联行。以学生成绩表为例,两者均可查出有成绩的学生,而NOTEXISTS则查出无成绩者。实际应用中,IN适合子查询结果集较小,EXISTS则更高效于大结果集。
零基础MySQL IN与EXISTS笔记总结
时间:2026-07-25
浏览:229
文章目录
适合刚接触子查询的MySQL初学者。本文通过同一套「学生/成绩」示例,详细讲解IN和EXISTS的用法与区别,帮助零基础用户快速掌握SQL子查询过滤技巧。

一、IN与EXISTS的核心作用
在MySQL中,IN和EXISTS常与子查询搭配,用于数据过滤。简单来说,就是先查看另一组数据,再决定当前表中的哪些行需要保留。
以下是直观理解:
| 关键字 | 通俗解释 |
|---|---|
| IN | 左边的值,是否在右边的列表中? |
| EXISTS | 对于当前行,括号内的子查询能否至少返回一行? |
二、准备示例数据
学生表 students
| student_id | name |
|---|---|
| 1 | 小明 |
| 2 | 小红 |
| 3 | 小刚 |
成绩表 scores
| score_id | student_id | subject | score |
|---|---|---|---|
| 101 | 1 | 语文 | 90 |
| 102 | 1 | 数学 | 85 |
| 103 | 2 | 语文 | 92 |
结论:小明、小红有成绩;小刚没有成绩。
三、IN:判断值是否在列表中
3.1 固定值列表
SELECT * FROM students WHERE student_id IN (1, 2, 5);
含义:查询学号为1、2或5的学生。
- 如果在列表中 → 条件为真,保留该行
- 如果不在 → 条件为假,排除该行
3.2 列表来自子查询
需求:找出有成绩的学生。
SELECT * FROM students WHERE student_id IN (SELECT student_id FROM scores);
执行逻辑:
- 先执行子查询:从
scores获取所有student_id,例如(1, 1, 2),去重后相当于列表(1, 2) - 再扫描
students:判断每个学生的学号是否在列表中 - 在列表中的学生被保留
逐步分析:
| 学生 | student_id | 在列表中? | 结果 |
|---|---|---|---|
| 小明 | 1 | 是 | 保留 |
| 小红 | 2 | 是 | 保留 |
| 小刚 | 3 | 否 | 排除 |
查询结果:
| student_id | name |
|---|---|
| 1 | 小明 |
| 2 | 小红 |
四、EXISTS:检查是否存在关联行
同样需求:找出有成绩的学生。
SELECT * FROM students s WHERE EXISTS (SELECT 1 FROM scores sc WHERE sc.student_id = s.student_id);
4.1 理解方式
对于外层每一行学生,执行一次内层子查询:
- 如果内层查询至少返回一行 →
EXISTS为真 → 保留该学生 - 如果内层查询返回零行 → 为假 → 排除该学生
注意:SELECT 1 只是占位符,EXISTS 只关心是否有行存在,不关心具体值。
4.2 逐步执行
小明(id=1)
- 成绩表中是否有
student_id = 1的记录?有 → 保留
小红(id=2)
- 是否有
student_id = 2的记录?有 → 保留
小刚(id=3)
- 是否有
student_id = 3的记录?没有 → 排除
结果与上面 IN 相同:小明、小红。
五、NOT EXISTS:找出没有成绩的学生
SELECT * FROM students s WHERE NOT EXISTS (SELECT 1 FROM scores sc WHERE sc.student_id = s.student_id);
| 学生 | 是否有成绩 | NOT EXISTS结果 | 是否保留? |
|---|---|---|---|
| 小明 | 有 | 假 | 否 |
| 小红 | 有 | 假 | 否 |
| 小刚 | 无 | 真 | 是 |
结果:
| student_id | name |
|---|---|
| 3 | 小刚 |
也可以使用 NOT IN 实现:
SELECT * FROM students WHERE student_id NOT IN (SELECT student_id FROM scores);
在干净数据中,结果同样是小刚。
注意:
NOT IN的子查询结果如果包含NULL,会导致意外行为;许多场景更推荐使用NOT EXISTS。初学者先了解这个差异即可。
六、IN与EXISTS的选择(入门视角)
多数业务中,两者可以写出等价结果,但思考角度不同:
| IN | EXISTS | |
|---|---|---|
| 思考方式 | 先有一份值列表,判断是否在其中 | 对当前行询问:是否存在匹配行 |
| 直观写法 | id IN (1,2,3) 或 id IN (子查询) | EXISTS (带关联条件的子查询) |
| 适用场景 | 列表较短,语义明确为“属于集合” | 语义明确为“是否存在关联数据” |
关于性能:具体取决于数据量、索引和优化器,不要死记“永远谁更快”。入门阶段,优先保证写对、读得懂。
七、与外键约束的关系(可选了解)
- 外键约束:插入数据时禁止指向不存在的学生
- IN / EXISTS:查询时筛选“是否存在关联成绩”等
外键是写入时的约束,而IN/EXISTS是查询时的过滤手段,两者共同帮助理解“表与表如何关联”。
八、一句话总结
IN:值是否在列表中。
EXISTS:对于当前行,子查询是否至少存在一行。
NOT EXISTS:对于当前行,是否不存在关联行。
以“找出有成绩的学生”为例:
- 用
IN:学号是否出现在成绩表的学号列表中 - 用
EXISTS:该学生在成绩表中能否找到记录
结果相同,但思考角度不同。
九、练习
- 用
IN查询有成绩的学生(默写一遍)。 - 用
EXISTS再写一遍。 - 用
NOT EXISTS查询没有成绩的学生。
能不看笔记写出正确SQL,这部分内容就掌握了。
笔记整理自零基础学习过程,示例表为 students / scores。
实用工具推荐
绿化、压缩、噪点和虚拟水印,自由调节做旧程度。
选择画质和输出格式,预览压缩前后的大小。