我見過很多不同形式的左反半連接。請允許我列出并命名每個想到的。以下查詢旨在回傳ROSTER_ID任何員工未使用的所有內容以及該名冊的所有者。
--1) NOT EXISTS, with a particular column selected in the subquery
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE NOT EXISTS (SELECT EMP_ID FROM EMPLOYEES WHERE EMP_ID = ROSTERS.EMP_ID)
--2) NOT EXISTS, with a particular column selected in the subquery and TOP (1) used
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE NOT EXISTS (SELECT TOP (1) EMP_ID FROM EMPLOYEES WHERE EMP_ID = ROSTERS.EMP_ID)
--3) NOT EXISTS, with all data selected in the subquery
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE NOT EXISTS (SELECT * FROM EMPLOYEES WHERE EMP_ID = ROSTERS.EMP_ID)
--4) NOT EXISTS, with all columns selected in the subquery and TOP (1) used
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE NOT EXISTS (SELECT TOP (1) * FROM EMPLOYEES WHERE EMP_ID = ROSTERS.EMP_ID)
--5) NOT EXISTS, but just use SELECT 1
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE NOT EXISTS (SELECT 1 FROM EMPLOYEES WHERE EMP_ID = ROSTERS.EMP_ID)
--6) NOT IN
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE EMP_ID NOT IN (SELECT EMP_ID FROM EMPLOYEES)
--7) LEFT JOIN
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
LEFT OUTER JOIN EMPLOYEES
ON EMPLOYEES.EMP_ID = ROSTERS.EMP_ID
WHERE EMPLOYEES.EMP_ID IS NULL
我的問題是:是否有任何客觀原因(例如性能、向后兼容性、可移植性、NULL 處理、易于測驗、可擴展性等)更喜歡任何特定的左反半連接方式?我也有興趣聽到主觀原因,例如風格問題或清晰度,但僅包括它們將是一個非答案。
我自己的研究僅指向以下內容,但這一切都很薄弱并且可能是主觀的:
- Microsoft 的 U-SQL 檔案暗示他們更喜歡在 T-SQL 中使用 NOT IN 版本(我的 #6)。
NULL處理IN總是令人擔憂,這是一個溫和的理由更喜歡它EXISTS。- 如果您非常關心向后兼容性,那么我認為我的 LEFT JOIN 語法在 1980 年代不起作用。
- 有些人喜歡使用
EXCEPT,但我不認為它適用于列僅出現在最外層的情況SELECT。
uj5u.com熱心網友回復:
不,除了不吸
Aaron 的文章已經包含了豐富的資訊,并且您已經發現了NOT IN與 NULLS 結合使用的危險。
我唯一可以補充的是,我沒有注意到討論的是,在使用時(not) exists,之前的東西是如何FROM喜歡select column或select top 1 *本質上是垃圾的。我什至向 sql server 發布了一個建議,以使用(anti) semi join table2 on <join condition>.
uj5u.com熱心網友回復:
EXISTS,NOT EXISTS回傳布林值。子查詢中提到的列 無關緊要,它只檢查它是否存在,具體TRUE/FALSE取決于SelectEXISTSwhere cluase
例如,
SELECT ROSTER_ID, ROSTER_OWNER
FROM ROSTERS
WHERE NOT EXISTS (SELECT 1/0 FROM EMPLOYEES WHERE EMP_ID = ROSTERS.EMP_ID)
在上面的通知1/0中不會拋出錯誤,這意味著什么?
所以你的 1),2),3),4),5) 在性能和結果上都是相等的。
LEFT JOIN:當您需要結果集中 LEFT JOIN 表中的列時使用它。
uj5u.com熱心網友回復:
我認為任何答案都沒有涵蓋所有內容,因此我嘗試將所有答案和評論放在一起:
- 實施例1至5,即
EXISTS實施例,均相同。這不容易證明(您可能會發現 KumarHarsh 的示例令人信服)并且依賴于您信任優化器。 - 不要使用示例 #6,即
IN. 你不能相信它與NULLs。 - Example #7, ie
LEFT JOIN可以復制結果,如果你將它用于普通(即不是anti)半連接。也有人懷疑優化器將如何處理它(見下面的鏈接)。主觀上,它似乎需要更多的打字,并且在傳達您的意圖方面并不是那么好。總的來說,最好避免。
總之,使用EXISTS. 使用 的示例 #2 和 #4TOP毫無意義地這樣做,因此您最好避免使用它們。至于您是否應該使用示例 #1、#3 或 #5,這只是個人喜好問題。我認為#5 最清楚地傳達了意圖,但這完全是一個見仁見智的問題。
這篇非常有用的文章也建議OUTER APPLY,但我認為沒有人認真對待。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/485778.html
下一篇:合并查詢
