Критерии фильтра SQL в критериях соединения или где предложение, которое более эффективно

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

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

Случай 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

RDBMS - это Sql Server 2005

ИЗМЕНИТЬ Если вторая часть критерия объединения или предложение where были проданы. Salesdate < какая-то фиксированная дата, поэтому на самом деле нет каких-либо критериев объединения двух таблиц, которые меняют ответ.

Ответ 1

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

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

Просто забота о том, чтобы держать вещи в чистоте и помещать вещи, где они принадлежат, ИМО.

Очевидно, что есть случаи с LEFT OUTER JOINs, где размещение критериев действительно влияет на то, какие результаты будут возвращены - эти случаи будут исключены из моей рекомендации, конечно.

Марк

Ответ 2

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

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

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

Ответ 3

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

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

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

Пример:

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

Если вам нужно получить второй столбец из таблицы 2, вы просто скопируете этот блок в блокнот, выполните поиск/повторную отправку "ABC" и престо и весь новый блок кода, готовый к вставке.

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

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

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

Ответ 4

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

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

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

Попробуйте это, чтобы увидеть разницу между 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

Ответ 5

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

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

  • Использование критериев в ВКЛЮЧЕНО не будет фильтровать/пропускать строки для выбора, а столбцы соединения будут иметь значение null на основе условий

  • Использование критериев в Где предложение может фильтровать/пропускать строки по всем результатам

Ответ 6

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

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

Ответ 7

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

Ответ 8

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

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

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

Ответ 9

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