Условие в СОЕДИНЕНИИ или ГДЕ - PullRequest
163 голосов
/ 19 июня 2009

Есть ли какая-либо разница (производительность, лучшие практики и т. Д.) Между помещением условия в предложение JOIN и предложением WHERE?

Например ...

-- Condition in JOIN
SELECT *
FROM dbo.Customers AS CUS
INNER JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
AND CUS.FirstName = 'John'

-- Condition in WHERE
SELECT *
FROM dbo.Customers AS CUS
INNER JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
WHERE CUS.FirstName = 'John'

Что вы предпочитаете (и, возможно, почему)?

Ответы [ 9 ]

134 голосов
/ 19 июня 2009

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

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

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

Например, вместо:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
    AND c.State = 'NY'
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
    AND a.Status = 1

Запись:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
WHERE c.State = 'NY'
    AND a.Status = 1

Но это, конечно, зависит.

108 голосов
/ 19 июня 2009

Для внутренних объединений я на самом деле не заметил разницы (но, как и во всех настройках производительности, вам нужно проверить свою базу данных в ваших условиях).

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

SELECT *
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
WHERE ORD.OrderDate >'20090515'

SELECT *
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
AND ORD.OrderDate >'20090515'

Первая выдаст вам только те записи, чей заказ датирован позднее 15 мая 2009 года, и тем самым преобразует левое соединение во внутреннее соединение. Второй даст эти записи плюс любые клиенты без заказов. Набор результатов сильно отличается в зависимости от того, где вы поставили условие. (Выберите *, если только в качестве примера, вы не должны, конечно, использовать в производственном коде.) Исключением является случай, когда вы хотите видеть только записи в одной таблице, но не в другой. Затем вы используете условие where для условия, а не для соединения.

SELECT *
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
WHERE ORD.OrderID is null
23 голосов
/ 19 июня 2009

Большинство продуктов RDBMS оптимизируют оба запроса одинаково. В «Настройка производительности SQL» Питера Гулутзана и Труди Пельцер они протестировали несколько брендов СУБД и не обнаружили различий в производительности.

Я предпочитаю хранить условия объединения отдельно от условий ограничения запросов.

Если вы используете OUTER JOIN, иногда необходимо поместить условия в предложение объединения.

10 голосов
/ 19 июня 2009

ГДЕ будет фильтроваться после того, как произошло СОЕДИНЕНИЕ.

Фильтр в JOIN для предотвращения добавления строк во время процесса JOIN.

3 голосов
/ 19 июня 2009

Я предпочитаю, чтобы JOIN объединял полные таблицы / представления, а затем использовал WHERE, чтобы ввести предикат результирующего набора.

Синтаксически чище.

2 голосов
/ 19 июня 2009

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

Я всегда слегка удивлен, когда кто-то показывает свой сравнительный анализ SQL, и он выполнил обе версии sproc 50000 раз в полночь на сервере разработчиков и сравнил среднее время.

0 голосов
/ 18 июля 2018

Лучше добавить условие в Join. Производительность важнее, чем удобочитаемость. Для больших наборов данных это имеет значение.

0 голосов
/ 19 июня 2009

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

0 голосов
/ 19 июня 2009

Помещение условия в объединение кажется мне "семантически неправильным", так как это не то, для чего объединения "для". Но это очень качественно.

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

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