EXISTS子查询通俗教程

一、核心: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个场景,不踩坑)

  1. 只需要判断“是否存在关联数据”,不需要具体数据(比如:有没有成绩、有没有订单);

  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就出错。

(注:)

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容