SQL中NOT IN與NOT EXISTS不等價(jià)的問(wèn)題
在對(duì)SQL語(yǔ)句進(jìn)行性能優(yōu)化時(shí),經(jīng)常用到一個(gè)技巧是將IN改寫(xiě)成EXISTS,這是等價(jià)改寫(xiě),并沒(méi)有什么問(wèn)題。問(wèn)題在于,將NOT IN改寫(xiě)成NOT EXISTS時(shí),結(jié)果未必一樣。
執(zhí)行環(huán)境:MySQL
一、舉例驗(yàn)證
例如,有如下一張表 rr 。要求:選擇4月2號(hào)的數(shù)據(jù),并且其type1是4月1號(hào)沒(méi)有的(從表看,就是4月2號(hào)C的那條)。

使用NOT IN ,單純按照這個(gè)條件去實(shí)現(xiàn)
select * from rr where create_date='2024-04-02' and type1 not in ( select type1 from rr where create_date='2024-04-01' ) ;

使用NOT EXISTS
select r1.* from rr as r1 where r1.create_date='2024-04-02' and not exists ( select r2.type1 from rr as r2 where r2.create_date='2024-04-01' and r1.type1=r2.type1 ) ;

主要原因是4月1號(hào)的數(shù)據(jù)中,存在type1為NULL的。如果該type1不是NULL,使用NOT IN就可以正確找出來(lái)結(jié)果了。
其中的原理涉及三值邏輯。
二、三值邏輯簡(jiǎn)述
以下的式子都會(huì)被判為unknown
1、 = NULL
2、> NULL
3、< NULL
4、<> NULL
NULL = NULL
unknown,它是因關(guān)系數(shù)據(jù)庫(kù)采用了NULL而被引入的“第三個(gè)真值”。
(這里還有一點(diǎn)需要注意:真值unknown和作為NULL的一種UNKNOWN(未知)是不同的東西。前者是明確的布爾類(lèi)型的真值,后者既不是值也不是變量。為了便于區(qū)分,前者采用粗體小寫(xiě)字母unknown,后者用普通的大寫(xiě)字母UNKNOWN表示。)
加上true和false,這三個(gè)真值之間有下面這樣的優(yōu)先級(jí)順序。
- AND 的情況:false > unknown > true
- OR 的情況:true > unknown > false
下面看具體例子,連同unknown一起理解下

三、附錄:用到的SQL
(運(yùn)行環(huán)境Mysql)
1、表 rr 的構(gòu)建
-- 使用了with語(yǔ)句 with rr as ( select '2024-04-01' as create_date,'A' as type1,001 as code1 union all select '2024-04-01' as create_date,'A' as type1,002 as code1 union all select '2024-04-01' as create_date,'A' as type1,002 as code1 union all select '2024-04-01' as create_date,'B' as type1,013 as code1 union all select '2024-04-01' as create_date,null as type1,013 as code1 union all select '2024-04-02' as create_date,'B' as type1,013 as code1 union all select '2024-04-02' as create_date,'C' as type1,109 as code1 union all select '2024-04-03' as create_date,'A' as type1,002 as code1 union all select '2024-04-04' as create_date,'A' as type1,002 as code1 )
2、 unknown的理解
set @a:=2, @b:=5, @c:= NULL ;
select @a+@b as result1,
case when (@b>@c) is true then 'true!'
when (@b>@c) is false then 'false!'
else 'unknown'
end as result2, -- 與NULL比較
case when (@a<@b and @b>@c) is true then 'true!'
when (@a<@b and @b>@c) is false then 'false!'
else 'unknown'
end as result3, -- and條件下 的優(yōu)先級(jí)展示
case when (@a<@b or @b>@c) is true then 'true!'
when (@a<@b or @b>@c) is false then 'false!'
else 'unknown'
end as result4, -- or條件下 的優(yōu)先級(jí)展示
case when (not(@b<>@c)) is true then 'true!'
when (not(@b<>@c)) is false then 'false!'
else 'unknown'
end as result5到此這篇關(guān)于SQL中NOT IN與NOT EXISTS不等價(jià)的問(wèn)題的文章就介紹到這了,更多相關(guān)SQL NOT IN與NOT EXISTS不等價(jià)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- sql語(yǔ)句優(yōu)化之用EXISTS替代IN、用NOT EXISTS替代NOT IN的語(yǔ)句
- MySQL: mysql is not running but lock exists 的解決方法
- mysql insert if not exists防止插入重復(fù)記錄的方法
- UCenter info: MySQL Query Error SQL:SELECT value FROM [Table]vars WHERE noteexists
- mysql not in、left join、IS NULL、NOT EXISTS 效率問(wèn)題記錄
- sql not in 與not exists使用中的細(xì)微差別
- Mysql中in和exists的區(qū)別?&?not?in、not?exists、left?join的相互轉(zhuǎn)換問(wèn)題
相關(guān)文章
親自教你使用?ChatGPT?編寫(xiě)?SQL?JOIN?查詢(xún)示例
這篇文章主要介紹了使用ChatGPT編寫(xiě)SQL?JOIN查詢(xún),作為一種語(yǔ)言模型,ChatGPT 可以就如何構(gòu)建復(fù)雜的 SQL 查詢(xún)和 JOIN 提供指導(dǎo)和建議,但它不能直接訪(fǎng)問(wèn) SQL 數(shù)據(jù)庫(kù),它可以幫助您了解語(yǔ)法、最佳實(shí)踐和有關(guān)如何構(gòu)建查詢(xún)以高效執(zhí)行的一般指導(dǎo),需要的朋友可以參考下2023-02-02
SQL Server 數(shù)據(jù)庫(kù)分區(qū)分表(水平分表)詳細(xì)步驟
最近幾個(gè)擔(dān)心網(wǎng)站數(shù)據(jù)量大會(huì)影響sqlserver數(shù)據(jù)庫(kù)的性能,所以提前將數(shù)據(jù)庫(kù)分表處理好,下面是ExceptionalBoy同學(xué)分享的詳細(xì)方法,需要的朋友可以參考下2021-03-03
SQL?Server使用SELECT?INTO實(shí)現(xiàn)表備份的代碼示例
在數(shù)據(jù)庫(kù)管理過(guò)程中,有時(shí)我們需要對(duì)表進(jìn)行備份,以防數(shù)據(jù)丟失或修改錯(cuò)誤,在?SQL?Server?中,可以使用?SELECT?INTO?語(yǔ)句將數(shù)據(jù)從一個(gè)表備份到另一個(gè)表,本文通過(guò)代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2025-01-01
SQL?Server數(shù)據(jù)庫(kù)分離和附加數(shù)據(jù)庫(kù)的操作步驟
數(shù)據(jù)庫(kù)的附加是數(shù)據(jù)庫(kù)在數(shù)據(jù)庫(kù)文件中添加到數(shù)據(jù)庫(kù)當(dāng)中的操作,下面這篇文章主要給大家介紹了關(guān)于SQL?Server數(shù)據(jù)庫(kù)分離和附加數(shù)據(jù)庫(kù)的操作步驟,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-10-10
大容量csv快速內(nèi)導(dǎo)入sqlserver的解決方法(推薦)
最近遇到這樣的問(wèn)題:導(dǎo)入csv 數(shù)據(jù),并對(duì)導(dǎo)入的數(shù)據(jù)增加一個(gè)新的列date datetime,下面通過(guò)本文給大家分享大容量csv快速內(nèi)導(dǎo)入sqlserver的解決方法,感興趣的朋友一起看看吧2017-07-07
SQL Server中利用正則表達(dá)式替換字符串的方法
這篇文章主要介紹了SQL Server中利用正則表達(dá)式替換字符串的方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-03-03
調(diào)整SQLServer2000運(yùn)行中數(shù)據(jù)庫(kù)結(jié)構(gòu)
這篇文章主要介紹了調(diào)整SQLServer2000運(yùn)行中數(shù)據(jù)庫(kù)結(jié)構(gòu),十分實(shí)用的一個(gè)功能,這里推薦給大家,有需要的小伙伴可以參考下。2015-04-04
使用SQL語(yǔ)句實(shí)現(xiàn)查詢(xún)排序,順序和倒序
這篇文章主要介紹了使用SQL語(yǔ)句實(shí)現(xiàn)查詢(xún)排序、順序和倒序,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05
SQL語(yǔ)句中含有乘號(hào)報(bào)錯(cuò)的處理辦法
這篇文章主要介紹了SQL語(yǔ)句中含有乘號(hào)報(bào)錯(cuò)的處理辦法,需要的朋友可以參考下2014-08-08

