SQL:左联接>;如果ON条件失败,WHERE语句中的条件是否被忽略?

SQL:左联接>;如果ON条件失败,WHERE语句中的条件是否被忽略?,sql,join,Sql,Join,如果您使用左联接,并且还有WHERE子句,那么如果您尝试联接的表不存在,WHERE子句中的所有条件是否都将被忽略 换句话说,我是否必须与来自左连接的id进行具体比较 SELECT distinct(watchedItems.id) FROM globalItems, watchedItems LEFT JOIN bidGroups ON bidGroups.bidGroupID = watchedItems.bidGroupID WHERE watchedItems.aid

如果您使用左联接,并且还有WHERE子句,那么如果您尝试联接的表不存在,WHERE子句中的所有条件是否都将被忽略

换句话说,我是否必须与来自左连接的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
如果左连接失败,它将不会被测试,因为bidGroup不存在?我知道如果没有左连接,它肯定会一直针对它进行测试,这意味着如果测试失败,整个语句将不会执行。但是我希望它在任何情况下都能执行(有bidGroups和没有bidGroups)。

如果表不存在,您的语句将不会解析,并将导致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是否为NULL的答案是no,您不必这样做,因为连接条件已经涵盖了这一点。

如果表不存在,您的语句将不会解析,并将导致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是否为NULL的答案是
,您不必这样做,因为连接条件已经涵盖了这一点。

如果左连接失败,缺少的行中的所有列都将具有NULL值,因此您的测试
bidGroups.bidGroupQty
将始终失败。如果您希望在左联接中缺少行的情况下测试成功,则您拥有的较长逻辑是正确的。

如果左联接失败,则缺少行的所有列的值都将为null,因此您的测试
bidGroups.bidGroupQty
将始终失败。如果您希望在左联接中缺少行的情况下测试成功,那么您拥有的较长逻辑是正确的。

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
子句中只会导致混淆。

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
子句中加入连接只会导致混淆。

首先,我不会混淆语法;
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

首先,我不会混合语法;
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

谢谢,糟糕,我刚刚意识到,我的问题的措辞有误。我的意思是,如果一个表是空的,或者LEFT JOIN中的条件不能满足。谢谢,糟糕,我刚刚意识到,我在问题的措辞上犯了一个错误。我的意思是,如果一个表是空的,或者左连接中的条件不能满足,这个答案给出的结果与OP的查询结果略有不同。当bidGroupQty>0位于WHERE子句中时,左侧ON子句中bidGroupQty0为的项连接,bidGroupQtyth为的项此答案给出的结果与OP的查询结果略有不同。当bidGroupQty>0位于WHERE子句中时,带有bidGroupQty0的项与左侧的ON子句连接,带有bidGroupQtyy的项需要停止使用隐式语法,这是近20年前被替换的糟糕编程实践。在某些数据库上,将隐式语法和显式语法结合在一起也会导致错误的结果。隐式语法更难维护(特别是当您想要添加左连接或不知道交叉连接是有意的还是偶然的时),并且更可能包含影响Resultls集的错误,例如偶然的交叉连接。感谢您的建议。我从来不知道两者之间有区别。对于阅读本文的其他人来说,这里有一个有用信息的链接:你需要停止使用隐式语法,这是一种几乎20年前被取代的糟糕的编程实践。在某些数据库上,将隐式语法和显式语法结合在一起也会导致错误的结果。隐式语法更难维护(特别是当您想要添加左连接或不知道交叉连接是有意的还是偶然的时),并且更可能包含影响Resultls集的错误,例如偶然的交叉连接。感谢您的建议。我从来不知道两者之间有区别。对于阅读本文的其他人,这里有一个链接,其中包含有用的信息: