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

长期稳定更新的攒劲资源: >>>点此立即查看<<<
在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 |
结论:小明、小红有成绩;小刚没有成绩。
SELECT * FROM students WHERE student_id IN (1, 2, 5);
含义:查询学号为1、2或5的学生。
需求:找出有成绩的学生。
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 | 小红 |
同样需求:找出有成绩的学生。
SELECT * FROM students s WHERE EXISTS (SELECT 1 FROM scores sc WHERE sc.student_id = s.student_id);
对于外层每一行学生,执行一次内层子查询:
EXISTS 为真 → 保留该学生注意:SELECT 1 只是占位符,EXISTS 只关心是否有行存在,不关心具体值。
小明(id=1)
student_id = 1 的记录?有 → 保留小红(id=2)
student_id = 2 的记录?有 → 保留小刚(id=3)
student_id = 3 的记录?没有 → 排除结果与上面 IN 相同:小明、小红。
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 | |
|---|---|---|
| 思考方式 | 先有一份值列表,判断是否在其中 | 对当前行询问:是否存在匹配行 |
| 直观写法 | id IN (1,2,3) 或 id IN (子查询) | EXISTS (带关联条件的子查询) |
| 适用场景 | 列表较短,语义明确为“属于集合” | 语义明确为“是否存在关联数据” |
关于性能:具体取决于数据量、索引和优化器,不要死记“永远谁更快”。入门阶段,优先保证写对、读得懂。
外键是写入时的约束,而IN/EXISTS是查询时的过滤手段,两者共同帮助理解“表与表如何关联”。
IN:值是否在列表中。
EXISTS:对于当前行,子查询是否至少存在一行。
NOT EXISTS:对于当前行,是否不存在关联行。
以“找出有成绩的学生”为例:
IN:学号是否出现在成绩表的学号列表中EXISTS:该学生在成绩表中能否找到记录结果相同,但思考角度不同。
IN 查询有成绩的学生(默写一遍)。EXISTS 再写一遍。NOT EXISTS 查询没有成绩的学生。能不看笔记写出正确SQL,这部分内容就掌握了。
笔记整理自零基础学习过程,示例表为 students / scores。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述