in 和 exists 已經成為我們日常查詢時候的常客了。很多時候他們2個都是可以互通實現的,但是,無論兄弟怎麼親,還是會有那麼一些差別的。 先搞個測試表 CREATE TABLE #Tmp1(ID INT,Col1 NVARCHAR(50)) CREATE TABLE #Tmp2(ID INT,T
in 和 exists 已經成為我們日常查詢時候的常客了。很多時候他們2個都是可以互通實現的,但是,無論兄弟怎麼親,還是會有那麼一些差別的。
先搞個測試表
CREATE TABLE #Tmp1(ID INT,Col1 NVARCHAR(50)) CREATE TABLE #Tmp2(ID INT,T1ID INT,Col1 NVARCHAR(50),Col2 NVARCHAR(50)) INSERT INTO #Tmp1 ( ID, Col1 ) VALUES ( 1, N'AAA'),( 2, N'BBB'),( 3, N'CCC'),( 4, N'DDD') INSERT INTO #Tmp2 ( ID, T1ID, Col1, Col2 ) VALUES ( 1, 1, N'aa1',N'aa!!'),( 5, 1, N'aa2',N'vv!!'),( 6, 3, N'cc3',N'VV!!')
然後一般來說,查#Tmp1 的ID存在於#Tmp2裡面的數據,以下2個語句都是等價的~
SELECT * FROM #Tmp1 a WHERE EXISTS(SELECT * FROM #Tmp2 WHERE a.ID = T1ID) SELECT * FROM #Tmp1 WHERE ID IN (SELECT T1ID FROM #Tmp2) ID Col1 ----------- -------------------------------------------------- 1 AAA 3 CCC ID Col1 ----------- -------------------------------------------------- 1 AAA 3 CCC
看~查到的是一樣的。然後現在要給點註意一點的地方了~
1、 使用exists 的時候因為exists後面跟的只是一個bool ,所以在exists() 括弧裡面跟在 select 和from之間,其實寫什麼都不重要,只要條件有結果返回,就OK。比方說
SELECT * FROM #Tmp1 a WHERE EXISTS(SELECT NULL FROM #Tmp2 WHERE a.ID = T1ID) SELECT * FROM #Tmp1 a WHERE EXISTS(SELECT * FROM #Tmp2 WHERE 1=0) ID Col1 ----------- -------------------------------------------------- 1 AAA 3 CCC ID Col1 ----------- --------------------------------------------------
先看第二句,因為子查詢裡面是一個恆假的表達式,並不返回任何行數,所以,外部的查詢結果一行都不會出來。這個好理解。
第一句即使你填的是select null 也沒所謂,因為只要有結果集返回,就OK了,甚至改成
SELECT * FROM #Tmp1 a WHERE EXISTS(SELECT null) ID Col1 ----------- -------------------------------------------------- 1 AAA 2 BBB 3 CCC 4 DDD
也全部返回了。為什麼,因為子查詢裡面每一個都有一行 null 返回出來,那 exists()的判定就是真。所以每一行都會被返回。這個是要註意的。
2 使用 in 的註意事項。
使用 in 的註意事項最主要是在相關子查詢上面,非相關子查詢倒是沒有什麼要特別註意的。但是有一個原則
比方說將上面一個語句改成一個相關子查詢,在子查詢裡面引用了#Tmp1 的ID,然後就變成以下的結果
SELECT * FROM #Tmp1 a WHERE ID IN (SELECT T1ID FROM #Tmp2 WHERE a.ID = T1ID) ID Col1 ----------- -------------------------------------------------- 1 AAA 3 CCC
感知不明顯是吧,再改動一下,以下這句在實際中並大部分情況並沒有任何的意義,只是用於示例。
SELECT * FROM #Tmp1 a WHERE ID IN (SELECT ID FROM #Tmp2 ) ID Col1 ----------- -------------------------------------------------- 1 AAA
看看這個語句,從執行結果來看,你可以知道是#Tmp2裡面的ID,但有沒有懷疑過是#Tmp1 自身的ID呢?能夠引用嗎?可以!!所以如以下慄子,有時候真會出現這種情況的喲~小心小心再小心哦~
SELECT * FROM #Tmp1 a WHERE ID IN (SELECT a.ID FROM #Tmp2 ) ID Col1 ----------- -------------------------------------------------- 1 AAA 2 BBB 3 CCC 4 DDD
3、 使用 in 的時候,尤其註意一個值 Null ! 可能在 in (select ID from XXX) 的時候感知不明顯,然而在 not in (select ID from XXX) 的時候!假如 ID 有一個是 Null ~恭喜你~整個結果集都不會返回值啦~~這就是任何值和Null比對都會是unknow 的結果擼~~╮(╯_╰)╭ ~知道會出問題才要小心哦~
4、 效率與性能 ——很多文章都有說這個,在XXX地方用exists 比較好,在ZZZ地方用 in 比較好~我的觀點是。即使是 XXX 的場景,也有 in 比 exists 效果好的地方!!一切要看實際哦~一定要測試~
額~大家應該都上班了~大家洗樓愉快~