EXISTS子查詢通俗教程

一、核心:EXISTS到底是什么?(一句話懂)

EXISTS = “存在”,核心作用:只判斷“有沒有”,不關(guān)心具體有多少條、具體是什么數(shù)據(jù),找到1條符合條件的就停止,返回“有”(true),找不到就返回“沒有”(false)。

通俗類比:找東西時,只要看到1個目標(biāo),就確認(rèn)“有”,不用把所有目標(biāo)都找出來。

學(xué)生場景SQL例子(3個不同角度,易懂不復(fù)雜)

例子1:正向判斷(基礎(chǔ)款,判斷“有”)

需求:查“有考試成績的學(xué)生”(只要有1次成績就顯示,不管分?jǐn)?shù))

SELECT 學(xué)生姓名 FROM 學(xué)生表 s WHERE EXISTS (SELECT 1 FROM 成績表 c WHERE c.學(xué)生ID = s.學(xué)生ID);

解讀:逐個檢查學(xué)生,只要成績表中有該學(xué)生的任意1條成績,就保留該學(xué)生。

例子2:帶條件的存在(進(jìn)階款,判斷“有符合條件的”)

需求:查“有不及格成績(<60分)的學(xué)生”(只要有1次不及格就顯示)

SELECT 學(xué)生姓名 FROM 學(xué)生表 s WHERE EXISTS (SELECT 1 FROM 成績表 c WHERE c.學(xué)生ID = s.學(xué)生ID AND c.成績 < 60);

解讀:不關(guān)心學(xué)生有多少及格成績,只判斷“有沒有不及格的”,找到1條就保留。

例子3:反向判斷(NOT EXISTS,判斷“沒有”)

需求:查“沒有請假記錄的學(xué)生”(全程無請假,才顯示)

SELECT 學(xué)生姓名 FROM 學(xué)生表 s WHERE NOT EXISTS (SELECT 1 FROM 請假表 q WHERE q.學(xué)生ID = s.學(xué)生ID);

解讀:逐個檢查學(xué)生,請假表中找不到該學(xué)生的任何請假記錄,就保留(“沒有”請假,符合條件)。

二、什么時候用EXISTS?(記2個場景,不踩坑)

  1. 只需要判斷“是否存在關(guān)聯(lián)數(shù)據(jù)”,不需要具體數(shù)據(jù)(比如:有沒有成績、有沒有訂單);

  2. 數(shù)據(jù)量大時(比如學(xué)生表、成績表各10萬條),用EXISTS比IN快。

三、EXISTS vs IN(核心區(qū)別,一眼看懂)

對比點 EXISTS IN
核心邏輯 判斷“有沒有”,找到1條就停 先查全量子查詢結(jié)果,再匹配
通俗類比 找筆:看到1支就確認(rèn)“有” 找筆:把所有筆都找出來,再確認(rèn)
效率 大數(shù)據(jù)量快(不做無用功) 大數(shù)據(jù)量慢(需查全量)
適用場景 判斷存在性、大數(shù)據(jù)量、子查詢有NULL 匹配具體數(shù)據(jù)、小數(shù)據(jù)量、子查詢無NULL
查詢結(jié)果 不受子查詢NULL影響,結(jié)果穩(wěn)定 子查詢有NULL時,結(jié)果會出錯(查不到數(shù)據(jù))

關(guān)鍵補充:兩者不是所有情況結(jié)果都一樣,核心差異在「子查詢有NULL值」時,具體看學(xué)生場景例子:

例子4:子查詢有NULL,結(jié)果不同(易踩坑)

需求:查“有成績的學(xué)生”(成績表中部分學(xué)生ID為NULL)

用EXISTS(正確,能查到有成績的學(xué)生):

SELECT 學(xué)生姓名 FROM 學(xué)生表 s WHERE EXISTS (SELECT 1 FROM 成績表 c WHERE c.學(xué)生ID = s.學(xué)生ID);

用IN(錯誤,查不到任何數(shù)據(jù)):

SELECT 學(xué)生姓名 FROM 學(xué)生表 WHERE 學(xué)生ID IN (SELECT 學(xué)生ID FROM 成績表); -- 子查詢有NULL,IN會返回空結(jié)果

解讀:IN遇到子查詢中的NULL值,會直接返回空結(jié)果(相當(dāng)于查不到任何數(shù)據(jù)),而EXISTS不受NULL影響,正常判斷“有沒有”。

四、明確區(qū)分:什么時候用IN,什么時候用EXISTS?(對比例子版,學(xué)生直接套)

核心:分兩種情況對比,既有「結(jié)果相同」的場景,也有「結(jié)果不同」的場景,結(jié)合例子一看就懂,直接套用即可。

場景1:結(jié)果相同(小數(shù)據(jù)量、子查詢無NULL,兩者都能用,僅效率有差異)

需求:查“有考試成績(子查詢無NULL)的學(xué)生”(小數(shù)據(jù)量:學(xué)生表50人,成績表200條)

方法1:用EXISTS(判斷存在性,效率略高)

SELECT 學(xué)生姓名 FROM 學(xué)生表 s WHERE EXISTS (SELECT 1 FROM 成績表 c WHERE c.學(xué)生ID = s.學(xué)生ID);

方法2:用IN(匹配具體數(shù)據(jù),結(jié)果一致)

SELECT 學(xué)生姓名 FROM 學(xué)生表 WHERE 學(xué)生ID IN (SELECT 學(xué)生ID FROM 成績表);

結(jié)果:兩條SQL查詢結(jié)果完全一致,都能查到所有有成績的學(xué)生。

選擇建議:小數(shù)據(jù)量無所謂,大數(shù)據(jù)量優(yōu)先用EXISTS;想寫起來簡潔,用IN。

場景2:結(jié)果相同(明確匹配具體值,兩者都能用)

需求:查“成績?yōu)?0分或90分的學(xué)生”(子查詢無NULL,小數(shù)據(jù)量)

方法1:用EXISTS(判斷“有符合條件的成績”)

SELECT 學(xué)生姓名 FROM 學(xué)生表 s WHERE EXISTS (SELECT 1 FROM 成績表 c WHERE c.學(xué)生ID = s.學(xué)生ID AND c.成績 IN (80,90));

方法2:用IN(匹配具體學(xué)生ID)

SELECT 學(xué)生姓名 FROM 學(xué)生表 WHERE 學(xué)生ID IN (SELECT 學(xué)生ID FROM 成績表 WHERE 成績 IN (80,90));

結(jié)果:兩條SQL查詢結(jié)果完全一致,都能查到成績?yōu)?0分或90分的學(xué)生。

選擇建議:這種場景用IN更簡潔,寫起來更省事。

場景3:結(jié)果不同(子查詢有NULL,僅EXISTS能用,IN會出錯)

需求:查“有成績的學(xué)生”(成績表中部分學(xué)生ID為NULL,小數(shù)據(jù)量)

方法1:用EXISTS(正確,結(jié)果正常)

SELECT 學(xué)生姓名 FROM 學(xué)生表 s WHERE EXISTS (SELECT 1 FROM 成績表 c WHERE c.學(xué)生ID = s.學(xué)生ID);

結(jié)果:能正常查到所有有成績的學(xué)生。

方法2:用IN(錯誤,無結(jié)果)

SELECT 學(xué)生姓名 FROM 學(xué)生表 WHERE 學(xué)生ID IN (SELECT 學(xué)生ID FROM 成績表);

結(jié)果:查不到任何數(shù)據(jù)(IN遇到子查詢NULL會返回空結(jié)果)。

選擇建議:子查詢有NULL,必須用EXISTS,避免出錯。

場景4:結(jié)果不同(大數(shù)據(jù)量,效率差異明顯,結(jié)果可能一致但體驗不同)

需求:查“有請假記錄的學(xué)生”(大數(shù)據(jù)量:學(xué)生表10萬條,請假表5萬條)

方法1:用EXISTS(高效,1秒出結(jié)果)

SELECT 學(xué)生姓名 FROM 學(xué)生表 s WHERE EXISTS (SELECT 1 FROM 請假表 q WHERE q.學(xué)生ID = s.學(xué)生ID);

方法2:用IN(低效,10秒+出結(jié)果)

SELECT 學(xué)生姓名 FROM 學(xué)生表 WHERE 學(xué)生ID IN (SELECT 學(xué)生ID FROM 請假表);

結(jié)果:兩條SQL查詢結(jié)果一致,但EXISTS效率遠(yuǎn)超IN。

選擇建議:大數(shù)據(jù)量,不管結(jié)果是否一致,優(yōu)先用EXISTS。

五、必記口訣(不會混)

EXISTS:只問有沒有,找到就收手;不受NULL影響,大數(shù)據(jù)量優(yōu);

IN:要找全所有,再去做匹配;小數(shù)據(jù)量好用,有NULL就出錯。

(注:)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容