Имеет ли значение условие? - PullRequest
6 голосов
/ 10 декабря 2011

Два следующих запроса дают мне разные результаты:

SELECT A.source_code, B.quantity
FROM Table_A AS A
LEFT JOIN Table_B AS B ON B.merchant_id = A.merchant_id
   AND B.agent_id = A.agent_id
   AND B.default IS NULL
WHERE A.month='2011-10-01'
   AND B.type='600'

А

SELECT A.source_code, B.quantity
FROM Table_A AS A
LEFT JOIN Table_B AS B ON B.merchant_id = A.merchant_id
   AND B.agent_id = A.agent_id
WHERE A.month='2011-10-01'
   AND B.type='600'
   AND B.default IS NULL

Я предполагал, что условие выполняет одну и ту же операцию в обоих запросах, только в разное время. Я что-то упустил?

Ответы [ 3 ]

3 голосов
/ 10 декабря 2011

Они есть и должны быть разными.

Рассмотрим случай, когда у вас есть a с b, который совпадает с идентификаторами продавца и продавца, и b.default не равно нулю.

В первом случае вы найдете a, а затем не найдете b, которые соответствуют критериям, поскольку нет идентификатора b, который соответствует идентификатору AND, и по умолчанию установлено значение null. Но поскольку это левое соединение, вы по-прежнему получаете запись с данными «a» в выводе.

Во втором случае вы найдете a и найдете соответствующий b. Но так как b не соответствует предложению WHERE, запись исключается из вывода.

Если вы выполняете полное объединение, установка условия в положение ON вместо WHERE не изменит выходных данных. Но при левом или правом соединении это действительно меняет вывод так, как я пытался описать выше.

1 голос
/ 10 декабря 2011

Первый покажет вам только соответствующие записи из B, которые также имеют значение NULL для default.

Второй вариант покажет вам все записи из B, поскольку фильтр применяется после выполнения OUTER JOIN. Поскольку несопоставленные записи отображаются со значениями NULL, это соответствует всем записям.

Однако вы также должны знать, что когда вы фильтруете таблицу JOIN ed в предложении WHERE, вы заставляете INNER JOIN, так что на самом деле у вас здесь две проблемы.

0 голосов
/ 10 декабря 2011

Не совсем, но в данном случае да.

Предложение WHERE фильтрует результирующий набор, тогда как предложение ON останавливает соединение строк в первую очередь. Результирующий набор может быть большим, что делает большую работу по обработке большого результирующего набора. Если бы вы присоединились к другим таблицам, это имело бы большое значение, потому что прекращение объединения строк раньше может отрезать огромное количество строк позже.

Большинство современных парсеров в любом случае оптимизируют запрос, поэтому эффект производительности должен быть одинаковым в любом случае.

Наконец, поскольку предложение WHERE фильтрует, при левом соединении будет сохранять хотя бы одну строку с условием в условии ON, но выбрасывать его с условием в предложении WHERE.

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