2011-06-20 72 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