SQL中NOT IN與NOT EXISTS不等價的問題
在對SQL語句進行性能優(yōu)化時,經(jīng)常用到一個技巧是將IN改寫成EXISTS,這是等價改寫,并沒有什么問題。問題在于,將NOT IN改寫成NOT EXISTS時,結(jié)果未必一樣。
執(zhí)行環(huán)境:MySQL
一、舉例驗證
例如,有如下一張表 rr 。要求:選擇4月2號的數(shù)據(jù),并且其type1是4月1號沒有的(從表看,就是4月2號C的那條)。
使用NOT IN ,單純按照這個條件去實現(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而被引入的“第三個真值”。
(這里還有一點需要注意:真值unknown和作為NULL的一種UNKNOWN(未知)是不同的東西。前者是明確的布爾類型的真值,后者既不是值也不是變量。為了便于區(qū)分,前者采用粗體小寫字母unknown,后者用普通的大寫字母UNKNOWN表示。)
加上true和false,這三個真值之間有下面這樣的優(yōu)先級順序。
- AND 的情況:false > unknown > true
- OR 的情況:true > unknown > false
下面看具體例子,連同unknown一起理解下
三、附錄:用到的SQL
(運行環(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使用中的細微差別
- 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ù)庫,它可以幫助您了解語法、最佳實踐和有關(guān)如何構(gòu)建查詢以高效執(zhí)行的一般指導(dǎo),需要的朋友可以參考下2023-02-02SQL Server 數(shù)據(jù)庫分區(qū)分表(水平分表)詳細步驟
最近幾個擔心網(wǎng)站數(shù)據(jù)量大會影響sqlserver數(shù)據(jù)庫的性能,所以提前將數(shù)據(jù)庫分表處理好,下面是ExceptionalBoy同學(xué)分享的詳細方法,需要的朋友可以參考下2021-03-03SQL?Server使用SELECT?INTO實現(xiàn)表備份的代碼示例
在數(shù)據(jù)庫管理過程中,有時我們需要對表進行備份,以防數(shù)據(jù)丟失或修改錯誤,在?SQL?Server?中,可以使用?SELECT?INTO?語句將數(shù)據(jù)從一個表備份到另一個表,本文通過代碼示例介紹的非常詳細,需要的朋友可以參考下2025-01-01SQL?Server數(shù)據(jù)庫分離和附加數(shù)據(jù)庫的操作步驟
數(shù)據(jù)庫的附加是數(shù)據(jù)庫在數(shù)據(jù)庫文件中添加到數(shù)據(jù)庫當中的操作,下面這篇文章主要給大家介紹了關(guān)于SQL?Server數(shù)據(jù)庫分離和附加數(shù)據(jù)庫的操作步驟,文中通過圖文介紹的非常詳細,需要的朋友可以參考下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調(diào)整SQLServer2000運行中數(shù)據(jù)庫結(jié)構(gòu)
這篇文章主要介紹了調(diào)整SQLServer2000運行中數(shù)據(jù)庫結(jié)構(gòu),十分實用的一個功能,這里推薦給大家,有需要的小伙伴可以參考下。2015-04-04