2011-06-20 70 views
0

如果使用LEFT JOIN並且還有WHERE子句,那麼如果試圖加入的表不存在,是否忽略了WHERE子句中的所有條件?SQL:LEFT JOIN>如果ON條件失敗,則忽略WHERE語句中的條件?

換句話說,我是否必須專門與來自LEFT JOIN的ID進行比較?

SELECT distinct(watchedItems.id) 
FROM globalItems, watchedItems 
    LEFT JOIN bidGroups ON bidGroups.bidGroupID = watchedItems.bidGroupID 

WHERE  
    watchedItems.aid = globalItems.aid 
    AND watchedItems.processRunning = 0 
    (watchedItems.bidGroupID IS NULL 
    OR (watchedItems.bidGroupID IS NOT NULL AND bidGroups.bidGroupQty > 0)) 

我可以寫,而不是整個最後一位剛剛

AND bidGroups.bidGroupQty > 0 

,它不會被測試,因爲如果LEFT JOIN失敗bidGroups不存在?我知道如果沒有LEFT JOIN,它肯定會一直對它進行測試,這意味着如果這個測試失敗了,整個語句就不會執行。但我希望在任何情況下都能執行它(帶和不帶bidGroups)。

+2

您需要停止使用隱式語法,這是很差的編程習慣,幾乎在20年前被取代。像在這裏完成的那樣組合隱式和顯式語法也會導致某些數據庫的結果不正確。隱式語法更難以維護(特別是當您想要添加左連接,或者如果您不知道交叉連接是有意的還是偶然的)並且更可能包含影響設置的錯誤(例如意外交叉連接)時。 – HLGEM

+0

感謝您的建議HLGEM。我從來不知道這兩者之間是有區別的。對於其他讀者來說,這裏有一個有用的信息鏈接:http://www.cactusjuice.com/blogs/archive/2006/12/12/SQL-Server-JOIN-Syntax-Explicit-vs-Implicit。aspx –

回答

2

如果表不存在,您的語句將不會解析並導致SQL異常。

編輯

我會寫你的查詢這種方式,爲便於閱讀:

SELECT distinct(watchedItems.id) 
FROM globalItems INNER JOIN 
    watchedItems ON globalItems.aid = watchedItems.aid LEFT JOIN 
    bidGroups ON bidGroups.bidGroupID = watchedItems.bidGroupID 
WHERE 
    watchedItems.processRunning = 0 
AND (watchedItems.bidGroupID IS NULL 
    OR (watchedItems.bidGroupID IS NOT NULL 
    AND bidGroups.bidGroupQty > 0) 
); 

答案是否需要檢查watchedItems.bigGroupID IS NOT NULL沒有,你不必因爲連接條件已經涵蓋了這一點。

+0

謝謝,Yuck,我剛剛意識到,我在我的問題的措辭中犯了一個錯誤。我的意思是,如果一張桌子是空的或LEFT JOIN中的條件不能滿足。 –

1

如果左連接失敗,缺失行的列將全部爲空,因此您的測試bidGroups.bidGroupQty將始終失敗。如果您希望測試成功完成左連接中缺少的行,則您所擁有的更長的邏輯是正確的。

0

where子句中的條件始終以書面形式強制執行,因此您需要添加空測試邏輯或將外連接的過濾條件移至子查詢。就個人而言,我會重寫查詢,如下所示:

SELECT DISTINCT (watcheditems.id) 
    FROM    globalitems 
     INNER JOIN watcheditems 
       ON watcheditems.aid = globalitems.aid 
     LEFT JOIN (SELECT bidgroupid 
         FROM bidgroups 
         WHERE bidgroups.bidgroupqty > 0) bg 
       ON bg.bidgroupid = watcheditems.bidgroupid 
WHERE watcheditems.processrunning = 0 

我提出的其他變化是將您的內部連接到from條款。通常,使用SQL99標準將聯接放在from子句中是一種更好的做法,但是您選擇使用哪種方法,應該是一致的。加入where子句和from子句中的聯合會導致混淆。

2

首先,我不會混合語法; ,JOIN混合是一個頭痛:)然後將條件移入LEFT JOIN而不是WHERE子句?

SELECT 
    distinct(watchedItems.id) 
FROM 
    globalItems 
INNER JOIN 
    watchedItems 
    ON watchedItems.aid = globalItems.aid 
LEFT JOIN 
    bidGroups 
    ON bidGroups.bidGroupID = watchedItems.bidGroupID 
    AND bidGroups.bidGroupQty > 0 
WHERE  
    watchedItems.processRunning = 0 
+0

+1感謝您的建議。 –

+0

這個答案給出了與OP的查詢有微妙差別的結果。當bidGroupQty> 0在WHERE子句中時,不會返回bidGroupQty <= 0的項目。通過將bidGroupQty> 0移動到LEFT JOIN的ON子句中,bidGroupQty <= 0的項目將不會被加入,而是將*從主查詢返回。 – krubo