T-SQL: дополнительные предикаты для JOIN против предложения WHERE - PullRequest
7 голосов
/ 07 сентября 2011

Есть ли разница между добавлением дополнительных предикатов в оператор JOIN и добавлением их в качестве дополнительных предложений в оператор WHERE?

Пример 1. Предикат в предложении WHERE

select emp.*
from Employee emp
left join Order o on emp.Id = o.EmployeeId
where o.Cancelled = 0

Пример 2. Предикат для оператора JOIN

select emp.*
from Employee emp
left join Order o on emp.Id = o.EmployeeId and o.Cancelled = 0

Ответы [ 4 ]

9 голосов
/ 07 сентября 2011

В первом операторе внешнее объединение фактически превращается во внутреннее объединение из-за условия WHERE, поскольку оно будет отфильтровывать все строки таблицы сотрудника, в которых не был найден заказ (поскольку тогда o.Cancelled будет равно NULL)

Так что два утверждения не делают одно и то же.

4 голосов
/ 07 сентября 2011

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

В обоих этих примерах предполагается, что предикатсравнивает столбец в «правой» таблице со скалярным значением.

Производительность
Похоже, что если предикат находится на JOIN, то "Правая таблица отфильтрована заранее.Если предикат является частью предложения WHERE, тогда все результаты возвращаются и фильтруются один раз в конце перед возвратом набора результатов.

Возвращенные данные
, если предикатчасть предложения WHERE, то в ситуации, когда «правильное» значение равно нулю (т. е. нет присоединяющейся строки), тогда вся строка не будет возвращена в конечном наборе результатов, поскольку предикатсравнивает значение с null и поэтому возвращает false.

3 голосов
/ 07 сентября 2011

Просто для рассмотрения случая, когда дополнительный предикат находится в столбце из левой таблицы, это все равно может иметь значение, как показано ниже.

WITH T1(N) AS
(
SELECT 1 UNION ALL
SELECT 2
), T2(N) AS
(
SELECT 1 UNION ALL
SELECT 2
)
SELECT T1.N, T2.N, 'ON' AS Clause
FROM T1 
LEFT JOIN T2 ON T1.N = T2.N AND T1.N=1
UNION ALL
SELECT T1.N, T2.N, 'WHERE' AS Clause
FROM T1 
LEFT JOIN T2 ON T1.N = T2.N 
WHERE T1.N=1

Возвращает

N           N           Clause
----------- ----------- ------
1           1           ON
2           NULL        ON
1           1           WHERE
0 голосов
/ 08 сентября 2011

Вот еще один пример (четыре случая)

insert into #tmp(1,"A")
insert into #tmp(2,"B")

select "first Query", a.*,b.* from #tmp a LEFT JOIN #tmp b
on a.id =b.id
and  a.id =1

union all

select "second Query", a.*,b.* from #tmp a LEFT JOIN #tmp b
on a.id =b.id
where a.id =1

union all

select "Third Query", a.*,b.* from #tmp a LEFT JOIN #tmp b
on a.id =b.id
and  b.id =1

union all

select "Fourth Query", a.*,b.* from #tmp a LEFT JOIN #tmp b
on a.id =b.id
where  b.id =1

Результаты:

first Query       1      A      1      A
first Query       2      B      NULL   NULL
second Query      1      A      1      A
Third Query       1      A      1      A
Third Query       2      B      NULL   NULL
Fourth Query      1      A      1      A
Fourth Query      1      A      1      A
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...