你真的會玩SQL嗎?EXISTS和IN之間的區別


你真的會玩SQL嗎?系列目錄

你真的會玩SQL嗎?之邏輯查詢處理階段

你真的會玩SQL嗎?和平大使 內連接、外連接

你真的會玩SQL嗎?三范式、數據完整性

你真的會玩SQL嗎?查詢指定節點及其所有父節點的方法

你真的會玩SQL嗎?讓人暈頭轉向的三值邏輯

你真的會玩SQL嗎?EXISTS和IN之間的區別

你真的會玩SQL嗎?無處不在的子查詢

你真的會玩SQL嗎?Case也瘋狂

你真的會玩SQL嗎?表表達式,排名函數

你真的會玩SQL嗎?簡單的 數據修改

你真的會玩SQL嗎?你所不知道的 數據聚合

你真的會玩SQL嗎?透視轉換的藝術

你真的會玩SQL嗎?冷落的Top和Apply

你真的會玩SQL嗎?實用函數方法匯總

你真的會玩SQL嗎?玩爆你的數據報表之存儲過程編寫(上)

你真的會玩SQL嗎?玩爆你的數據報表之存儲過程編寫(下)

 

此文是繼文章 你真的會玩SQL嗎?三值邏輯 而補充的,那來探討下為什么有人會建議有些地方用EXISTS代替in

EXISTSIN之間的區別

1.EXISTS只返回TRUE或FALSE,不會返回UNKNOWN。

2.IN當遇到包含NULL的情況,那么就會返回UNKNOWN。

 

當查詢的列包含NULL時,NOT EXISTS正常返回TRUE或FALSE。

而NOT IN可能返回空集,如下

1:val IN(val1,val2,...,NULL),永遠不會返回FALSE,而是返回TRUE或UNKNOWN。

2:val NOT IN(val1,val2,...,NULL),永遠不會返回TRUE,而是返回NOT TRUE或NOT UNKNOWN。

 

看個示例:

Test1表

select t.[name] from Test as t

where  exists (select t1.orderid from Test1 as t1 where t1.[name]=t.[name])

返回 aaa,ccc,ddd

 

select t.[name] from Test as t

where  t.[name] in  (select t1.[] from Test1 as t1)

返回 aaa,ccc,ddd

 

select t.[name] from Test as t

where  not exists (select t1.orderid from Test1 as t1 where t1.[name]=t.[name])

返回 bbb

 

select t.[name] from Test as t

where  t.[name] not in  (select t1.[name] from Test1 as t1)

返回空集

練習

以下對就返回哪三值?

答案

View Code

 用例數據庫文件 你真的會玩SQL嗎?之邏輯查詢處理階段 文末

/*寫一條查詢語句,返回在2007年下過訂單,而在2008年沒有下過訂單的客戶。
涉及的表:Sales.Customers表和Sales.Orders表。用exists
期望的輸出:*/
custid      companyname
----------- ----------------------------------------
21          Customer KIDPX
23          Customer WVFAF
33          Customer FVXPQ
36          Customer LVJSO
43          Customer UISOJ
51          Customer PVDZC
85          Customer ENQZT

參考SQL:

--answer:
select custid, companyname
from Sales.Customers as C
where EXISTS
  (select *
   from Sales.Orders as O
   where O.custid = C.custid
     and O.orderdate >= '20070101'
     and O.orderdate < '20080101')
  and not EXISTS
  (select *
   from Sales.Orders as O
   where O.custid = C.custid
     and O.orderdate >= '20080101'
     and O.orderdate < '20090101');
/*
1.先處理外層查詢,從Sales.Customers表別名C中取出一個元組,將元組相關列值custid傳給內層查詢
2.執行第一層內層查詢,Sales.Orders表別名O,應用where子句返回滿足條件O.custid = C.custid和orderdate在2007年至2008年
3.執行第二層內層查詢,Sales.Orders表別名O應用where子句返回滿足條件O.custid = C.custid和orderdate在2008年至2009年的值
4.執行not EXISTS,外查詢根據子查詢返回的結果集得到滿足條件的行
*/
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM