2017-02-21 3 views
0

Если у меня есть этот запрос:MYSQL - использование и в РЕГИСТРИРУЙТЕСЬ против ИНЕКЕ

select * from tableA 
left outer join tableB on tableA.id=tableB.id 
AND tableB.foo = 1 
where tableA.owner=10 

я получаю 29 результатов, но если я перееду, что и в выражении WHERE вроде:

select * from tableA 
left outer join tableB on tableA.id=tableB.id 
where tableA.owner=10 
AND tableB.foo = 1 

I то получите только 17 результатов.

Я просмотрел все вокруг и не могу найти окончательное руководство относительно того, как использование AND отличается при использовании его в JOIN по сравнению с предложением WHERE. Кто-нибудь может мне это объяснить?

Кроме того, если я делаю что-то вроде AND tableB.foo = NULL в JOIN, все мои поля tableB.foo имеют NULL в результатах запроса, даже если они не являются нулевыми в таблице. Имеет ли значение AND в предложении JOIN это поле в выборе FROM перед тем, как он фильтруется в предложении WHERE?

+0

вы можете посмотреть здесь: http://stackoverflow.com/a/15706298/7416478 –

ответ

1

Все критерии для таблицы, в которой вы находитесь, должны быть в условии JOIN (как и ваш первый запрос). Помещая это в предложение WHERE (например, ваш второй запрос), неявно преобразует OUTER JOIN в INNER JOIN.

Что касается вашего вопроса о AND tableB.foo = NULL, который не является правильным синтаксисом MySQL. Для NULL требуется special treatment, используя такие операторы, как IS NULL. Вместо этого вы должны использовать AND tableB.foo IS NULL.

1

Внешнее соединение объединяется так же, как и внутреннее соединение. С добавлением, что, когда нет соответствия для записи, фиктивная запись со всеми столбцами, установленными в null, объединяется (так что вы все равно получите строку из первой таблицы в своих результатах).

В вашем первом запросе вы ищете совпадения в таблицеB с одинаковым идентификатором и foo = 1. Для записей в таблице A без такого соответствия вы все равно получаете строку результатов (со всеми полями tableA null).

Во втором запросе вы ищете совпадения в таблице Б с тем же идентификатором. Для записей в таблице A без такого совпадения вы все равно получаете строку результатов (со всеми полями tableA null). Затем в вашем аргументе where вы сохраняете только строки с foo = 1. Это отклоняет все внешние записи (поскольку их foo имеет значение NULL), и вы находитесь там, где вы были бы с простым внутренним соединением.

Поэтому всегда ставьте все критерии на внешнюю таблицу в предложении ON. (Существует одно исключение: анти-соединение, но вы можете узнать этот шаблон в другой раз.)

Смежные вопросы