Лучше сделать равное соединение в предложении from или предложении where - PullRequest
11 голосов
/ 14 января 2011

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

Например, следующее эквивалентно. Мой вопрос - есть ли причина использовать один стиль над другим?

SELECT * 
FROM A
INNER JOIN B ON A.A_ID = B.A_ID
            AND A.DURATION = 3.00

... против:

SELECT * 
FROM A
INNER JOIN B ON A.A_ID = B.A_ID
WHERE A.DURATION = 3.00

Ответы [ 6 ]

10 голосов
/ 01 ноября 2011

Вообще говоря, это не имеет смысловой разницы.

Есть один крайний случай, когда он может это сделать.Если (не рекомендуется) конструкция GROUP BY ALL добавлена ​​к запросу, как показано ниже.

DECLARE @A TABLE(A_ID INT, DURATION DECIMAL(3,2) )
INSERT INTO @A VALUES(1,2.00)

DECLARE @B TABLE(A_ID INT)
INSERT INTO @B VALUES(1)

/*Returns one row*/
SELECT *
FROM @A A
INNER JOIN @B B ON A.A_ID = B.A_ID
WHERE A.DURATION = 3.00
GROUP BY ALL A.A_ID, A.DURATION, B.A_ID

/*Returns zero rows*/    
SELECT *
FROM @A A
INNER JOIN @B B ON A.A_ID = B.A_ID  AND A.DURATION = 3.00
GROUP BY ALL A.A_ID, A.DURATION, B.A_ID
9 голосов
/ 14 января 2011

Это вопрос стиля. Как правило, вы хотите поместить условия, которые определяют «форму» результирующего набора, в предложение FROM (т. Е. Те, которые определяют, какие строки из каждой таблицы должны объединяться для получения результата), тогда как те условия, которые фильтр набор результатов должен быть в предложении WHERE. Для ВНУТРЕННИХ СОЕДИНЕНИЙ эффекты одинаковы, но если задействованы ВНЕШНИЕ СОЕДИНЕНИЯ (ВЛЕВО, ВПРАВО), это становится намного понятнее.


В вашем первом примере я оставляю вопрос "как это связано с таблицей B?" когда я встречаю это странное условие в JOIN. В то время как во втором я могу пропустить предложение FROM (и все JOIN), если меня это не интересует, и просто посмотреть условия, которые определяют, будут ли строки возвращаться в предложении WHERE.

6 голосов
/ 14 января 2011

Это тип JOIN, который имеет значение.
Нет никакой разницы, любая версия предоставленного запроса будет использовать тот же план выполнения, потому что вы имеете дело с INNER JOIN.

При работе с OUTER JOIN (IE: LEFT, RIGHT) существует разница огромная между двумя версиями, потому что применяется критерий *1009* после СОЕДИНЕНИЕ сделано. Если критерий указан в предложении ON, то критерии применяются до , и выполняется СОЕДИНЕНИЕ, что может существенно повлиять на наборы результатов.

3 голосов
/ 14 января 2011

Для SQL Server 2000+ планы запросов для каждого из этих запросов будут идентичны, а следовательно, и производительность тоже.

Это можно проверить с помощью SSMS для отображения фактического плана выполнения для каждогозапросы, нажимающие CTRL + M перед выполнением вашего запроса.Панель результатов будет иметь дополнительную вкладку, которая показывает вам план выполнения.Вы увидите, что в этом случае оба плана совпадают.

1 голос
/ 14 января 2011

Это вопрос стиля. Оптимизатор сделает все возможное.

0 голосов
/ 21 марта 2012
    --Samples for time of join wheather can we write condition at where or ON 
create table #emp(id int ,teamid int)
create table #team(tid int,name char(2))
insert into #emp values(1,1)
insert into #emp values(2,1)
insert into #emp values(3,2)
insert into #emp values(4,0)

insert into #team values(1,'A')
insert into #team values(2,'B')
insert into #team values(3,'C')

--select * from #emp
--select * from #team

--on inner join => there is no difference in Query Exc. Plan
--select * from #emp e join #team t on e.teamid=t.tid where e.teamid=2
--select * from #emp e join #team t on e.teamid=t.tid and e.teamid=2


/*on outetr join see the differnence If dealing with an OUTER JOIN (IE: LEFT, RIGHT), 
there is a huge difference between the two versions because the WHERE criteria is applied after the JOIN is made. 
If the criteria is specified in the ON clause, the criteria is applied before the JOIN is made which can made a considerable difference 
between the result sets.*/
select * from #emp e left join #team t on e.teamid=t.tid
select * from #emp e left join #team t on e.teamid=t.tid where e.teamid=2
select * from #emp e left join #team t on e.teamid=t.tid and  (e.teamid=2 or t.tid=1) and t.name='A'


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