Home [SQL] 檢查資料是否存在 Exists、Not Exists
Post
Cancel

[SQL] 檢查資料是否存在 Exists、Not Exists

Exists

EXISTS運算子用於判斷查詢子句是否有記錄,如果有一筆或多筆記錄存在回傳 True,否則傳回 False。 (該子查詢實際上並不返回任何數據,而是返回值TrueFalse)

EXISTSIN的使用效率的問題,通常採用exists要比in效率高,因為IN不走索引,但要看實際情況具體使用:

  • 當內表小外表大時,EXISTS的效率< in的效率;
  • 當內表大外表小時,EXISTS的效率> in的效率。 總結一下就是,內表小用in,外表小用EXISTS。 (內表小用in,內表大用exists)

語法

1
exists (subquery)

subquery 是受限的 SELECT 語句 (不允許有 COMPUTE 子句和 INTO 關鍵字)。

1
2
3
select ...
from ...
where exists (subquery)

該語法可以理解為:將主查詢的數據,放到子查詢中做條件驗証,根據驗証結果(True 或 False)來作為主查詢的數據結果是否得以保留。

要注意的是,EXISTSNOT EXISTS只判斷子查詢是否回傳結果,而不關心結果的特定內容。使用時,子查詢可以與主查詢的欄位進行關聯,以便根據子查詢的結果進行篩選和篩選。

原理

  • exists(sql返回結果集為真)
  • not exists(sql不返回結果集為真或返回結果集為假)
1
2
select * from a where exists (select * from b where a.id = b.id)
select * from a where not exists (select * from b where a.id = b.id)

sql語句使用了 existsnot exists 後的執行順序是:先執行「外查詢」再執行「內查詢」。 (這和學的子查詢概念就”衝突了” XD)

執行步驟 (使用exists)

執行順序是:先執行外查詢,再執行子查詢

  1. 首先執行「外查詢」 select * from a,然後從「外查詢」的資料取出一條資料傳給「內查詢」。
  2. 「內查詢」執行 select * from b,「外查詢」傳入的資料和「內查詢」獲得資料根據where後面的條件做匹對,如果存在資料滿足a.id=b.id則返回true,如果一條都不滿足則返回false
  3. 「內查詢」返回true,則「外查詢」的這行資料保留,反之「內查詢」返回false則「外查詢」的這行資料不顯示。「外查詢」的所有資料逐行查詢匹對。

not existsexists的用法相反,

Exists : 強調的是是否返回結果集,不要求知道返回什麼,比如: select name from student where sex = ‘m’ and mark exists(select 1 from grade where …) ,只要exists引導的子句有結果集返回,那麼exists這個條件就算成立了,大家注意返回的欄位始終為1,如果改成”select 2 from grade where …“,那麼返回的欄位就是2,這個數字沒有意義。所以exists子句不在乎返回什麼,而是在乎是不是有結果集返回。

範例一:在子查詢中使用 NULL,仍會傳回結果集

Select Null

1
2
3
select *
from Customers
where exists(select null)

同等於:select * from Customers

因為NULL在資料庫中是一個值(它是一個未知的值),在出現NULL值的地方EXISTS結構都會傳回真。

Where 1=1、 Select 1、select null

由於EXISTS結構的工作原理,所以下面的語句所實現的功能是一樣的。 同等於:select * from a

1
2
select * from a
where exists(select 1)
1
2
select * from a
where exists(select null)
1
2
select * from a
where 1=1

範例二:Exists

顯示有販賣業績的負責人之負責人ID與負責人姓名

1
2
3
4
5
--顯示有販賣業績的負責人之負責人ID與負責人姓名
select A.負責人ID, A.負責人姓名
from [負責人清單] A
where exists 
(select 1 from [販賣資料] B where B.負責人ID = A.負責人ID)

執行結果

1
2
3
4
5
6
7
8
負責人ID	負責人姓名
1	鈴木
2	小野
3	齋藤
5	小林
6	伊藤
7	佐瀨
8	宇賀神

範例三: Not Exists

NOT EXISTS 的作用與 EXISTS 相反。 如果子查詢未傳回任何資料列,便滿足 NOT EXISTS 中的 WHERE 子句。

顯示沒有販賣業績的負責人之負責人ID與負責人姓名

1
2
3
4
5
--顯示沒有販賣業績的負責人之負責人ID與負責人姓名
select A.負責人ID, A.負責人姓名
from [負責人清單] A
where not exists 
(select 1 from [販賣資料] B where B.負責人ID = A.負責人ID)

執行結果

1
2
3
負責人ID	負責人姓名
4	藤本
9	岡田

範例四:Exists + Except 差集

取得包含於負責人清單,但不包含分店負責人清單中的負責人的總販賣業績(販賣單價*數量)。(差集,可以使用Except)

1
2
3
4
5
6
7
8
9
10
--取得包含於負責人清單,但不包含分店負責人清單中的負責人的總販賣業績(販賣單價*數量)
select  sum(B.販賣單價*A.數量) "總業績"
from [dbo].[販賣資料] A
join [dbo].[商品清單] B on B.商品ID = A.商品ID
where exists
(
	select [負責人ID] from [dbo].[負責人清單]
	except
	select [分店負責人ID] from [dbo].[分店負責人清單]
)

執行結果

1
2
總業績
4625000

Select 1、Select Null

select 1select unll一般用來當條件使用,比如:

  • exists(select 1 from table)
  • exists(select null from table)

MSDN Exists [SQL] Select 1、Select null SQL笔记-select 1与select null [SQL] SQL語句的執行順序、EXISTS執行順序、EXISTS和IN執行效率

This post is licensed under CC BY 4.0 by the author.