Критерии фильтра SQL в критериях соединения или в предложении где более эффективно - PullRequest
25 голосов
/ 10 сентября 2009

У меня относительно простой запрос, объединяющий две таблицы. Критерии «где» могут быть выражены либо в критериях объединения, либо в виде предложения «где». Мне интересно, что является более эффективным.

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

Дело 1

select salesman.salesmanid, max(sales.quantity)
from salesman
inner join sales  on salesman.salesmanid =sales.salesmanid 
                  and sales.salesdate < salesman.promotiondate
group by salesman.salesmanid 

Дело 2

select salesman.salesmanid, max(sales.quantity)
from salesman
inner join sales  on salesman.salesmanid =sales.salesmanid 
where sales.salesdate < salesman.promotiondate
group by salesman.salesmanid 

Примечание. В случае 1 отсутствует предложение where

СУБД - Sql Server 2005

EDIT Если вторым элементом критериев соединения или предложением where было sales.salesdate <некоторая фиксированная дата, то это фактически не является критерием объединения двух таблиц, что меняет ответ.

Ответы [ 9 ]

27 голосов
/ 10 сентября 2009

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

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

Просто вопрос поддержания вещей в чистоте и размещения вещей на своих местах, ИМО.

Очевидно, что есть случаи с ЛЕВЫМИ ВНЕШНИМИ СОЕДИНЕНИЯМИ, в которых размещение критериев имеет значение с точки зрения того, какие результаты возвращаются - эти случаи, конечно, будут исключены из моей рекомендации.

Марк

3 голосов
/ 06 июня 2013

Я предпочитаю иметь какие-либо жестко закодированные критерии в соединении. Это делает SQL намного более читабельным и переносимым.

Дискретность: Вы можете точно увидеть, какие данные вы собираетесь получить, потому что все критерии таблицы записаны прямо в соединении. В больших утверждениях критерии могут быть скрыты в 50 других выражениях, и их легко пропустить.

Портативность: Вы можете просто скопировать кусок из предложения FROM и вставить его в другое место. Это дает объединения и любые критерии, которые вам нужны. Если вы всегда используете эти критерии при объединении этих двух таблиц, то размещение их в соединении является наиболее логичным.

Например:

FROM
table1 t1
JOIN table2 t2_ABC ON
  t1.c1 = t2_ABC.c1 AND
  t2_ABC.c2 = 'ABC'

Если вам нужно вытащить второй столбец из таблицы 2, просто скопируйте этот блок в Блокнот, выполните поиск / переопределение «ABC» и Presto и весь новый блок кода, готовый для вставки обратно.

Дополнительно: Также легче переключаться между внутренним и внешним объединением, не беспокоясь о каких-либо критериях, которые могут присутствовать в предложении WHERE.

Я резервирую предложение WHERE строго для критериев времени выполнения, где это возможно.

Что касается эффективности: Если вы имеете в виду скорость исключения, то, как все говорили, это избыточно. Если вы имеете в виду более простую отладку и повторное использование, тогда я предпочитаю вариант 1.

3 голосов
/ 10 сентября 2009

Вы можете запустить оценщик плана выполнения и SQL Server Profiler, чтобы увидеть, как они складываются друг с другом.

Тем не менее, они семантически одинаковы под капотом в соответствии с этим MVP SQL Server:

http://www.eggheadcafe.com/conversation.aspx?messageid=29145383&threadid=29145379

2 голосов
/ 02 марта 2017

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

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

  1. Использование критериев в предложении ON не будет фильтровать / пропускать строки для выбора, вместо этого столбцы соединения будут нулевыми в зависимости от условий

  2. Использование критериев в Где выражение может фильтровать / пропускать строки в целом результатах

1 голос
/ 10 сентября 2009

Я не думаю, что вы найдете окончательный ответ на этот вопрос, который применим ко всем случаям. Эти 2 не всегда взаимозаменяемы - поскольку для некоторых запросов (некоторые левые объединения) вы получите разные результаты, поместив критерии в WHERE против строки FROM.

В вашем случае вам следует оценить оба этих запроса. В SSMS вы можете просматривать приблизительные и фактические планы выполнения обоих этих запросов - это было бы хорошим первым шагом в определении того, что является более оптимальным. Вы также можете просмотреть время и ввод / вывод для каждого (установить время для статистики, включить и установить статистику) - и это также даст вам информацию для принятия решения.

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

Попробуйте, чтобы увидеть разницу между 2 ...

SET STATISTICS IO ON
SET STATISTICS TIME ON

select salesman.salesmanid, 
       max(sales.quantity)
from   salesmaninner join sales on salesman.salesmanid =sales.salesmanid
       and sales.salesdate < salesman.promotiondate
group by salesman.salesmanid

select salesman.salesmanid, 
       max(sales.quantity)
from   salesmaninner join sales on salesman.salesmanid = sales.salesmanid 
where  sales.salesdate < salesman.promotiondate
group by salesman.salesmanid

SET STATISTICS TIME OFF
SET STATISTICS IO OFF
0 голосов
/ 13 апреля 2017

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

0 голосов
/ 10 сентября 2009

Ознакомьтесь с Примерным планом выполнения в SQL Management Studio !! Как уже говорили другие, вы находитесь во власти анализатора, независимо от того, что вы делаете, поэтому доверяйте его оценкам. Я полагаю, что два предоставленных вами плана приведут к точно такому же плану.

Если это попытка изменить культуру развития, выберите ту, которая дает вам лучший план; для тех, кто идентичен, следуйте культуре

Я прокомментировал это на других постах "эффективности", таких как этот (и искренний, и саркастический) - если это то место, где находятся ваши узкие места, тогда высокие пять для вас и вашей команды.

0 голосов
/ 10 сентября 2009

Ни один из них не является более эффективным, использование метода WHERE считается старым способом сделать это (http://msdn.microsoft.com/en-us/library/ms190014.aspx). Вы можете посмотреть план выполнения и увидеть, что они делают то же самое.

0 голосов
/ 10 сентября 2009

Это может показаться легкомысленным, но ответом является любой запрос, для которого анализатор запросов создает наиболее эффективный план.

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

...