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

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

三、附錄:用到的SQL
(運(yùn)行環(huán)境Mysql)
1、表 rr 的構(gòu)建
-- 使用了with語句 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)先級展示
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)先級展示
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不等價的問題的文章就介紹到這了,更多相關(guān)SQL NOT IN與NOT EXISTS不等價內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- sql語句優(yōu)化之用EXISTS替代IN、用NOT EXISTS替代NOT IN的語句
- 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 效率問題記錄
- sql not in 與not exists使用中的細(xì)微差別
- Mysql中in和exists的區(qū)別?&?not?in、not?exists、left?join的相互轉(zhuǎn)換問題
相關(guān)文章
親自教你使用?ChatGPT?編寫?SQL?JOIN?查詢示例
這篇文章主要介紹了使用ChatGPT編寫SQL?JOIN查詢,作為一種語言模型,ChatGPT 可以就如何構(gòu)建復(fù)雜的 SQL 查詢和 JOIN 提供指導(dǎo)和建議,但它不能直接訪問 SQL 數(shù)據(jù)庫,它可以幫助您了解語法、最佳實(shí)踐和有關(guān)如何構(gòu)建查詢以高效執(zhí)行的一般指導(dǎo),需要的朋友可以參考下2023-02-02
SQL Server 數(shù)據(jù)庫分區(qū)分表(水平分表)詳細(xì)步驟
最近幾個擔(dān)心網(wǎng)站數(shù)據(jù)量大會影響sqlserver數(shù)據(jù)庫的性能,所以提前將數(shù)據(jù)庫分表處理好,下面是ExceptionalBoy同學(xué)分享的詳細(xì)方法,需要的朋友可以參考下2021-03-03
SQL?Server使用SELECT?INTO實(shí)現(xiàn)表備份的代碼示例
在數(shù)據(jù)庫管理過程中,有時我們需要對表進(jìn)行備份,以防數(shù)據(jù)丟失或修改錯誤,在?SQL?Server?中,可以使用?SELECT?INTO?語句將數(shù)據(jù)從一個表備份到另一個表,本文通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2025-01-01
SQL?Server數(shù)據(jù)庫分離和附加數(shù)據(jù)庫的操作步驟
數(shù)據(jù)庫的附加是數(shù)據(jù)庫在數(shù)據(jù)庫文件中添加到數(shù)據(jù)庫當(dāng)中的操作,下面這篇文章主要給大家介紹了關(guān)于SQL?Server數(shù)據(jù)庫分離和附加數(shù)據(jù)庫的操作步驟,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-10-10
大容量csv快速內(nèi)導(dǎo)入sqlserver的解決方法(推薦)
最近遇到這樣的問題:導(dǎo)入csv 數(shù)據(jù),并對導(dǎo)入的數(shù)據(jù)增加一個新的列date datetime,下面通過本文給大家分享大容量csv快速內(nèi)導(dǎo)入sqlserver的解決方法,感興趣的朋友一起看看吧2017-07-07
SQL Server中利用正則表達(dá)式替換字符串的方法
這篇文章主要介紹了SQL Server中利用正則表達(dá)式替換字符串的方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-03-03
調(diào)整SQLServer2000運(yùn)行中數(shù)據(jù)庫結(jié)構(gòu)
這篇文章主要介紹了調(diào)整SQLServer2000運(yùn)行中數(shù)據(jù)庫結(jié)構(gòu),十分實(shí)用的一個功能,這里推薦給大家,有需要的小伙伴可以參考下。2015-04-04
使用SQL語句實(shí)現(xiàn)查詢排序,順序和倒序
這篇文章主要介紹了使用SQL語句實(shí)現(xiàn)查詢排序、順序和倒序,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-05-05

