SQL: LEFT JOIN> Если условие ON не выполнено, игнорируются ли условия в выражении WHERE? - PullRequest
0 голосов
/ 20 июня 2011

Если вы используете LEFT JOIN и также имеете предложение WHERE, все условия в предложении WHERE игнорируются, если таблица, к которой вы пытались присоединиться, не существует?

Другими словами, могу ли янужно специально сравнивать с идентификатором из LEFT JOIN?

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

, и он не будет проверен, потому что bidGroups несуществует, если LEFT JOIN не удается?Я знаю, что без LEFT JOIN он все время будет проверяться, что означает, что если этот тест не пройден, весь оператор не будет выполнен.Но я хочу, чтобы это было выполнено в любом случае (с и без bidGroups.)

Ответы [ 4 ]

2 голосов
/ 20 июня 2011

Во-первых, я бы не стал смешивать синтаксис;смесь , и 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
2 голосов
/ 20 июня 2011

Если таблица не существует, ваш оператор не будет проанализирован и приведет к исключению SQL.

РЕДАКТИРОВАТЬ

Iнаписал бы ваш запрос таким образом, для удобства чтения:

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: нет , вам уже не нужно в качестве условия объединенияохватывает это.

1 голос
/ 20 июня 2011

В случае сбоя левого соединения столбцы из отсутствующей строки будут иметь значение null, поэтому ваш тест bidGroups.bidGroupQty всегда будет неудачным.Если вы хотите, чтобы тест завершился успешно при отсутствии строки в левом соединении, более длинная логика у вас правильная.

0 голосов
/ 20 июня 2011

Условия в предложении 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 может привести к путанице.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...