天天看點

你真的會玩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

EXISTS和IN之間的差別

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

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

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

傳回 bbb

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

傳回空集

練習

以下對就傳回哪三值?

你真的會玩SQL嗎?EXISTS和IN之間的差別
答案
你真的會玩SQL嗎?EXISTS和IN之間的差別
你真的會玩SQL嗎?EXISTS和IN之間的差別

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

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:

你真的會玩SQL嗎?EXISTS和IN之間的差別
你真的會玩SQL嗎?EXISTS和IN之間的差別
--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,外查詢根據子查詢傳回的結果集得到滿足條件的行
*/      

作者:歡醉

公衆号【一個碼農的日常】 技術群:319931204 1号群: 437802986 2号群: 340250479

出處:http://zhangs1986.cnblogs.com/

碼雲:https://gitee.com/huanzui

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。

Top