基于 SQL 中的 EXISTS 運(yùn)算符為我們提供了一種基于其他數(shù)據(jù)是否存在(或不存在)來(lái)檢索數(shù)據(jù)的簡(jiǎn)便方法。更具體地說(shuō),它是一個(gè)邏輯運(yùn)算符,用于評(píng)估子查詢的結(jié)果,并返回一個(gè)布爾值,該值指示是否返回了行。盡管 IN 運(yùn)算符可用于類似的目的,但需要注意它們之間的一些差異。今天的博客將介紹如何使用 EXISTS 運(yùn)算符的幾個(gè)示例,并提供一些指導(dǎo),說(shuō)明何時(shí)應(yīng)使用 EXISTS 而不是 IN


EXISTS 在實(shí)踐中的應(yīng)用


盡管 EXISTS 運(yùn)算符可以在 SELECTUPDATEINSERT DELETE 語(yǔ)句中使用,但為了保持簡(jiǎn)單,我們將重點(diǎn)介紹 SELECT 查詢。因此,我們將使用的語(yǔ)法將非常類似于以下形式:


 


我們將在 PostgreSQL 的幾個(gè)表上執(zhí)行我們的查詢——比如客戶和賬戶表,這些表在銀行數(shù)據(jù)庫(kù)中很常見(jiàn)。下面是在 Navicat for PostgreSQL 網(wǎng)格視圖中顯示的這些表:



現(xiàn)在,我們可以使用以下查詢來(lái)查看所有具有與其 customer_id 相關(guān)聯(lián)的賬戶的客戶:


 


以下是在 Navicat Premium 的查詢編輯器中執(zhí)行上述查詢的結(jié)果:



使用 NOT EXISTS


相反地,在 EXISTS 運(yùn)算符前加上 NOT 關(guān)鍵字會(huì)導(dǎo)致查詢只選擇子查詢中沒(méi)有匹配行的記錄。我們可以使用 NOT EXISTS 來(lái)檢索所有孤立的賬戶,即沒(méi)有關(guān)聯(lián)客戶的賬戶:


 


由于客戶表中沒(méi)有該 ID 的客戶,所以它返回了客戶 #4 的賬戶。



Joins 替換 EXISTS


使用 EXISTS 運(yùn)算符的查詢可能執(zhí)行起來(lái)有點(diǎn)慢,因?yàn)樽硬樵冃枰獙?duì)外層查詢的每一行都執(zhí)行一次。因此,你應(yīng)該盡可能考慮使用連接。事實(shí)上,我們可以使用 LEFT JOIN 來(lái)重寫(xiě)上面的EXISTS 查詢:


 

 


IN vs EXISTS 運(yùn)算符


盡管 IN 運(yùn)算符通常用于為列的某個(gè)值列表設(shè)置過(guò)濾器,但它也可以應(yīng)用于子查詢的結(jié)果。以下是我們第一個(gè)查詢的等效查詢,但這次使用的是 IN 而不是 EXISTS


 


請(qǐng)注意,我們只能選擇想要進(jìn)行比較的列,而不能選擇 SELECT *。不過(guò),IN 查詢會(huì)產(chǎn)生相同的結(jié)果:



由于這兩個(gè)操作符非常相似,數(shù)據(jù)庫(kù)開(kāi)發(fā)人員往往不確定應(yīng)該使用哪一個(gè)。一般來(lái)說(shuō), 當(dāng)你想根據(jù)特定值列表篩選行時(shí),應(yīng)該使用 IN 操作符。當(dāng)你想檢查子查詢中是否存在滿足某些條件的行時(shí),應(yīng)該使用 EXISTS