翻譯|使用教程|編輯:吉煒煒|2024-10-25 09:56:43.420|閱讀 119 次
概述:本文將以 PostgreSQL dvdrental 數(shù)據(jù)庫為例,介紹反連接的類型以及如何編寫反連接,以及如何在 Navicat Premium Lite 17 中編寫和執(zhí)行查詢。
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
SQL 最強(qiáng)大的功能之一是 JOIN 操作,它提供了一種優(yōu)雅而簡單的方法,將一個(gè)表中的每一條記錄與另一個(gè)表中的每一條記錄結(jié)合起來。不過,有時(shí)我們可能想從一個(gè)表中找到另一個(gè)表中沒有的值。正如我們將在今天的文章中看到的,通過包含一個(gè)謂詞來連接表,連接也可以用于此目的。這種連接被稱為反連接,對于回答各種與業(yè)務(wù)相關(guān)的問題很有幫助,例如:
本文將以 PostgreSQL dvdrental 數(shù)據(jù)庫 為例,介紹反連接的類型以及如何編寫反連接。 我們將在 Navicat Premium Lite 17 中編寫和執(zhí)行查詢。
反連接的兩種類型
這是兩種類型的反連接:
下圖中 藍(lán)色 顯示部分表示返回的行:
下一節(jié)將以左反連接為例,介紹我們可以用來創(chuàng)建反連接的幾種不同語法。
使用 EXISTS 的左反連接
比方說,我們想在 dvdrental 數(shù)據(jù)庫中找到所有沒有出現(xiàn)在任何電影中的演員。遺憾的是,SQL 沒有這種操作的內(nèi)置語法,但我們可以使用 EXISTS,或更具體地說,使用 NOT EXISTS 來模擬這種操作。下面是這種查詢的結(jié)果:
SELECT * FROM actor a WHERE NOT EXISTS ( SELECT * FROM film_actor fa WHERE a.actor_id = fa.actor_id )
若我們在 Navicat Premium Lite 17 中運(yùn)行它,我們會(huì)獲得下面的結(jié)果:
請注意 NOT IN!
既然 EXISTS 和 IN 是等價(jià)的,你可能會(huì)得出結(jié)論,NOT EXISTS 和 NOT IN 也是等價(jià)的,但事實(shí)并非總是如此!只有當(dāng)右表(本例中為 film_actor)的外鍵(actor_id)上有 NOT NULL 約束時(shí),它們才是等價(jià)的。
在這個(gè)特定示例中,由于 actor_id 列上的 NOT NULL 約束,NOT IN 查詢會(huì)返回相同的結(jié)果:
如果 actor_id 列允許空值,則將返回空結(jié)果集。我們可以通過下面的查詢來驗(yàn)證這一點(diǎn):
SELECT * FROM actor WHERE actor_id NOT IN (1, 2, 3, 4, 5, NULL)
上述查詢沒有返回任何行,因?yàn)樵?SQL 中,NULL 代表一個(gè)未知值。由于我們無法確定 actor_id 是否在一個(gè)值集中(其中一個(gè)值是未知的),因此整個(gè)謂詞(predicate)就變成了未知(UNKNOWN)!
要避免 NOT IN 語法帶來的危險(xiǎn),最簡單的方法就是堅(jiān)持使用 NOT EXISTS。因?yàn)?DBA 可能會(huì)暫時(shí)關(guān)閉該約束以加載一些數(shù)據(jù),從而使你的查詢在此期間毫無用處。
替代語法
正如介紹中提到的,也可以使用左連接和右連接執(zhí)行反連接。要做到這一點(diǎn),需要添加一個(gè)帶有 IS NULL 謂詞的 WHERE 子句。下面是該語法的 LEFT JOIN 版本:
SELECT a.* FROM actor a LEFT JOIN film_actor fa ON a.actor_id = fa.actor_id WHERE fa.actor_id IS NULL
請注意,左/右連接語法的運(yùn)行速度可能會(huì)更慢,因?yàn)椴樵儍?yōu)化器不會(huì)將其識(shí)別為反連接操作。
結(jié)語
在今天的文章中,我們學(xué)習(xí)了如何使用三種不同的 SQL 語法來模擬左反連接。其中,NOT EXISTS 應(yīng)該是首選,因?yàn)樗茏詈玫貍鬟_(dá)反連接的意圖,而且執(zhí)行速度最快。
如果您有興趣試用 Navicat Premium Lite 17,它適用于 Windows、macOS 和 Linux 操作系統(tǒng),你可以點(diǎn)此下載或咨詢。
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@fc6vip.cn