Разница заключается в том, где условие логически оценивается, что, в свою очередь, может повлиять на набор результатов.
В ваших примерах (переформатированных) у вас есть:
Пример 1
SELECT COUNT(*)
FROM A LEFT JOIN B ON a.id = b.id
WHERE a.status = 2 AND b.id is NULL
Пример 2
SELECT COUNT(*)
FROM A LEFT JOIN B ON a.id = b.id AND a.status = 2
WHERE b.id is NULL
В первом случае применяется LEFT JOIN и генерируется результирующий набор; затем это фильтруется двумя условиями в предложении WHERE.
Во втором случае LEFT JOIN формируется с условием фильтра на a.status
, и в некоторых случаях может изменить набор результатов из LEFT JOIN. Этот набор результатов затем фильтруется с помощью основного предложения WHERE.
Пример 2 по существу эквивалентен:
Пример 2А
SELECT COUNT(*)
FROM (SELECT * FROM A WHERE a.status = 2) AS A
LEFT JOIN B ON a.id = b.id
WHERE b.id is NULL
Для некоторых запросов (но, вероятно, не для этого) разница может иметь значение.
Давайте попробуем создать несколько простых примеров данных:
Table A Table B
id status id
4 2 1
5 3
Пример 1 будет иметь промежуточный набор результатов:
a.id a.status b.id
4 2 null
5 3 null
и предложение WHERE исключает второй ряд.
Пример 2 будет иметь промежуточный набор результатов:
a.id a.status b.id
4 2 null
В этом примере чистый результат такой же, и я не смог найти данные, которые не совпадают.
Если условие запроса, которое перемещается, находится во внешней объединенной таблице и является более сложным, чем простое равенство, то вы можете увидеть эффект.