一、核心:EXISTS到底是什么?(一句话懂)
EXISTS = “存在”,核心作用:只判断“有没有”,不关心具体有多少条、具体是什么数据,找到1条符合条件的就停止,返回“有”(true),找不到就返回“没有”(false)。
通俗类比:找东西时,只要看到1个目标,就确认“有”,不用把所有目标都找出来。
学生场景SQL例子(3个不同角度,易懂不复杂)
例子1:正向判断(基础款,判断“有”)
需求:查“有考试成绩的学生”(只要有1次成绩就显示,不管分数)
SELECT 学生姓名 FROM 学生表 s WHERE EXISTS (SELECT 1 FROM 成绩表 c WHERE c.学生ID = s.学生ID);
解读:逐个检查学生,只要成绩表中有该学生的任意1条成绩,就保留该学生。
例子2:带条件的存在(进阶款,判断“有符合条件的”)
需求:查“有不及格成绩(<60分)的学生”(只要有1次不及格就显示)
SELECT 学生姓名 FROM 学生表 s WHERE EXISTS (SELECT 1 FROM 成绩表 c WHERE c.学生ID = s.学生ID AND c.成绩 < 60);
解读:不关心学生有多少及格成绩,只判断“有没有不及格的”,找到1条就保留。
例子3:反向判断(NOT EXISTS,判断“没有”)
需求:查“没有请假记录的学生”(全程无请假,才显示)
SELECT 学生姓名 FROM 学生表 s WHERE NOT EXISTS (SELECT 1 FROM 请假表 q WHERE q.学生ID = s.学生ID);
解读:逐个检查学生,请假表中找不到该学生的任何请假记录,就保留(“没有”请假,符合条件)。
二、什么时候用EXISTS?(记2个场景,不踩坑)
只需要判断“是否存在关联数据”,不需要具体数据(比如:有没有成绩、有没有订单);
数据量大时(比如学生表、成绩表各10万条),用EXISTS比IN快。
三、EXISTS vs IN(核心区别,一眼看懂)
| 对比点 | EXISTS | IN |
|---|---|---|
| 核心逻辑 | 判断“有没有”,找到1条就停 | 先查全量子查询结果,再匹配 |
| 通俗类比 | 找笔:看到1支就确认“有” | 找笔:把所有笔都找出来,再确认 |
| 效率 | 大数据量快(不做无用功) | 大数据量慢(需查全量) |
| 适用场景 | 判断存在性、大数据量、子查询有NULL | 匹配具体数据、小数据量、子查询无NULL |
| 查询结果 | 不受子查询NULL影响,结果稳定 | 子查询有NULL时,结果会出错(查不到数据) |
关键补充:两者不是所有情况结果都一样,核心差异在「子查询有NULL值」时,具体看学生场景例子:
例子4:子查询有NULL,结果不同(易踩坑)
需求:查“有成绩的学生”(成绩表中部分学生ID为NULL)
用EXISTS(正确,能查到有成绩的学生):
SELECT 学生姓名 FROM 学生表 s WHERE EXISTS (SELECT 1 FROM 成绩表 c WHERE c.学生ID = s.学生ID);
用IN(错误,查不到任何数据):
SELECT 学生姓名 FROM 学生表 WHERE 学生ID IN (SELECT 学生ID FROM 成绩表); -- 子查询有NULL,IN会返回空结果
解读:IN遇到子查询中的NULL值,会直接返回空结果(相当于查不到任何数据),而EXISTS不受NULL影响,正常判断“有没有”。
四、明确区分:什么时候用IN,什么时候用EXISTS?(对比例子版,学生直接套)
核心:分两种情况对比,既有「结果相同」的场景,也有「结果不同」的场景,结合例子一看就懂,直接套用即可。
场景1:结果相同(小数据量、子查询无NULL,两者都能用,仅效率有差异)
需求:查“有考试成绩(子查询无NULL)的学生”(小数据量:学生表50人,成绩表200条)
方法1:用EXISTS(判断存在性,效率略高)
SELECT 学生姓名 FROM 学生表 s WHERE EXISTS (SELECT 1 FROM 成绩表 c WHERE c.学生ID = s.学生ID);
方法2:用IN(匹配具体数据,结果一致)
SELECT 学生姓名 FROM 学生表 WHERE 学生ID IN (SELECT 学生ID FROM 成绩表);
结果:两条SQL查询结果完全一致,都能查到所有有成绩的学生。
选择建议:小数据量无所谓,大数据量优先用EXISTS;想写起来简洁,用IN。
场景2:结果相同(明确匹配具体值,两者都能用)
需求:查“成绩为80分或90分的学生”(子查询无NULL,小数据量)
方法1:用EXISTS(判断“有符合条件的成绩”)
SELECT 学生姓名 FROM 学生表 s WHERE EXISTS (SELECT 1 FROM 成绩表 c WHERE c.学生ID = s.学生ID AND c.成绩 IN (80,90));
方法2:用IN(匹配具体学生ID)
SELECT 学生姓名 FROM 学生表 WHERE 学生ID IN (SELECT 学生ID FROM 成绩表 WHERE 成绩 IN (80,90));
结果:两条SQL查询结果完全一致,都能查到成绩为80分或90分的学生。
选择建议:这种场景用IN更简洁,写起来更省事。
场景3:结果不同(子查询有NULL,仅EXISTS能用,IN会出错)
需求:查“有成绩的学生”(成绩表中部分学生ID为NULL,小数据量)
方法1:用EXISTS(正确,结果正常)
SELECT 学生姓名 FROM 学生表 s WHERE EXISTS (SELECT 1 FROM 成绩表 c WHERE c.学生ID = s.学生ID);
结果:能正常查到所有有成绩的学生。
方法2:用IN(错误,无结果)
SELECT 学生姓名 FROM 学生表 WHERE 学生ID IN (SELECT 学生ID FROM 成绩表);
结果:查不到任何数据(IN遇到子查询NULL会返回空结果)。
选择建议:子查询有NULL,必须用EXISTS,避免出错。
场景4:结果不同(大数据量,效率差异明显,结果可能一致但体验不同)
需求:查“有请假记录的学生”(大数据量:学生表10万条,请假表5万条)
方法1:用EXISTS(高效,1秒出结果)
SELECT 学生姓名 FROM 学生表 s WHERE EXISTS (SELECT 1 FROM 请假表 q WHERE q.学生ID = s.学生ID);
方法2:用IN(低效,10秒+出结果)
SELECT 学生姓名 FROM 学生表 WHERE 学生ID IN (SELECT 学生ID FROM 请假表);
结果:两条SQL查询结果一致,但EXISTS效率远超IN。
选择建议:大数据量,不管结果是否一致,优先用EXISTS。
五、必记口诀(不会混)
EXISTS:只问有没有,找到就收手;不受NULL影响,大数据量优;
IN:要找全所有,再去做匹配;小数据量好用,有NULL就出错。
(注:)