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