Разница между фильтрацией запросов в JOIN и где?
в SQL я пытаюсь фильтровать результаты на основе идентификатора и задаюсь вопросом, есть ли какая-либо логическая разница между
SELECT value
FROM table1
JOIN table2 ON table1.id = table2.id
WHERE table1.id = 1
и
SELECT value
FROM table1
JOIN table2 ON table1.id = table2.id AND table1.id = 1
мне кажется, что логика отличается, хотя вы всегда будете получать один и тот же набор результатов, но мне было интересно, есть ли какие-либо условия, при которых вы получите два разных результирующих набора (или они всегда будут возвращать одинаковые два результирующих набора)
3 ответов
ответ нет разница, но:
Я всегда предпочитаю делать следующее.
- всегда Присоединиться К Условиям на
ON
п. - всегда ставить фильтр на
where
п.
это делает запрос более читабельный.
поэтому я буду использовать этот запрос:
SELECT value
FROM table1
INNER JOIN table2
ON table1.id = table2.id
WHERE table1.id = 1
однако, когда вы используете OUTER JOIN'S
есть большая разница в сохранении фильтра в ON
условие и Where
состояние.
Логическая Обработка Запросов
следующий список содержит общую форму запроса вместе с номерами шагов, назначенными в соответствии с порядком, в котором логически обрабатываются различные предложения.
(5) SELECT (5-2) DISTINCT (5-3) TOP(<top_specification>) (5-1) <select_list>
(1) FROM (1-J) <left_table> <join_type> JOIN <right_table> ON <on_predicate>
| (1-A) <left_table> <apply_type> APPLY <right_table_expression> AS <alias>
| (1-P) <left_table> PIVOT(<pivot_specification>) AS <alias>
| (1-U) <left_table> UNPIVOT(<unpivot_specification>) AS <alias>
(2) WHERE <where_predicate>
(3) GROUP BY <group_by_specification>
(4) HAVING <having_predicate>
(6) ORDER BY <order_by_list>;
схема логических запросов
(1) от: от фаза определяет исходные таблицы запроса и обрабатывает табличные операторы. Каждый оператор таблицы применяет ряд суб этапов. Например, фазы, участвующие в соединении, являются (1-J1) Декартовое произведение, (1-J2) на фильтре, (1-J3) добавить внешние строки. От фаза генерирует виртуальную таблицу VT1.
(1-J1) Декартовое произведение: эта фаза выполняет Декартовое произведение (перекрестное соединение) между двумя таблицами, участвующими в операторе таблицы, генерирующий ВТ1-разъема j1.
- (1-J2) фильтр: эта фаза фильтрует строки из VT1-J1 на основе
предикат, который появляется в предложении ON (
). Только строки, для которых предикат принимает значение TRUE, вставляются в ВТ1-J2 для. - (1-J3) Добавить Внешние Строки: если указано внешнее соединение (в отличие от CROSS JOIN или INNER JOIN), строки из сохраненной таблицы или таблиц для которых совпадение не найдено, добавляются строки из VT1-J2 как внешний строк, создавая ВТ1-Ж3.
- (2) здесь: эта фаза фильтрует строки из VT1 на основе предикат, который появляется в предложении WHERE (). Только строки, для которых предикат принимает значение TRUE, вставляются в VT2.
- (3) GROUP BY: этот этап упорядочивает строки из VT2 в группах на основе в списке столбцов, указанном в предложении GROUP BY, генерируется VT3. В конечном счете, в каждой группе будет одна строка результатов.
- (4) иметь: фильтры этого участка группы из VT3 на основе
предикат, который появляется в предложении HAVING (
). Вставляются только группы, для которых предикат принимает значение TRUE на VT4 по. - (5) SELECT: эта фаза обрабатывает элементы в предложении SELECT, производя ВТ5.
- (5-1) оценка выражений: этот этап оценивает выражения в список выбора, генерирующий VT5-1.
- (5-2) DISTINCT: эта фаза удаляет повторяющиеся строки из VT5-1, генерирующий ВТ5-2.
- (5-3) верх: эта фаза фильтрует указанное верхнее число или процент строк из VT5-2 на основе логического порядка, определенного порядком П., создавая таблицы ВТ5-3.
- (6) заказ мимо: этот участок сортирует строки от VT5-3 согласно список столбцов, указанный в предложении ORDER BY, генерирующем курсор Из vc6.
это ссылка это отличная ссылка.
в то время как нет никакой разницы при использовании ВНУТРЕННИЕ СОЕДИНЕНИЯ, как отметил VR46, существует значительная разница при использовании ВНЕШНИЕ СОЕДИНЕНИЯ и оценка значения во второй таблице (для левых соединений - первая таблица для правых соединений). Рассмотрим следующую настройку:
DECLARE @Table1 TABLE ([ID] int)
DECLARE @Table2 TABLE ([Table1ID] int, [Value] varchar(50))
INSERT INTO @Table1
VALUES
(1),
(2),
(3)
INSERT INTO @Table2
VALUES
(1, 'test'),
(1, 'hello'),
(2, 'goodbye')
если мы выберем из него с помощью левого внешнего соединения и поставим условие в предложении where:
SELECT * FROM @Table1 T1
LEFT OUTER JOIN @Table2 T2
ON T1.ID = T2.Table1ID
WHERE T2.Table1ID = 1
мы получаем следующее результаты:
ID Table1ID Value
----------- ----------- --------------------------------------------------
1 1 test
1 1 hello
это потому, что предложение where ограничивает результирующий набор, поэтому мы включаем только записи из таблицы 1, которые имеют идентификатор 1. Однако, если мы переместим условие в предложение on:
SELECT * FROM @Table1 T1
LEFT OUTER JOIN @Table2 T2
ON T1.ID = T2.Table1ID
AND T2.Table1ID = 1
мы получаем следующие результаты:
ID Table1ID Value
----------- ----------- --------------------------------------------------
1 1 test
1 1 hello
2 NULL NULL
3 NULL NULL
это потому, что мы больше не фильтруем результирующий набор по идентификатору таблицы 1-скорее мы фильтруем соединение. Таким образом, несмотря на то, что идентификатор table1 из 2 имеет совпадение во второй таблице, это исключено из соединения, но не из результирующего набора (отсюда значения null).
Итак, для внутренних соединений это не имеет значения, но вы должны сохранить его в предложении where для удобочитаемости и согласованности. Однако для внешних соединений вы должны знать, что имеет значение, куда вы ставите условие, поскольку это повлияет на ваш результирующий набор.
Я думаю, что ответ, помеченный как "правильный", не является правильным. Почему? Я пытаюсь объяснить:
У нас есть мнение
" всегда держите условия соединения в предложении ON всегда помещайте фильтр В где пункт"
и это неправильно. Если вы находитесь во внутреннем соединении, каждый раз Ставьте параметры фильтра в предложение ON, а не в where. Ты спрашиваешь почему? Попробуйте представить сложный запрос с общим количеством таблиц 10(f.e. каждая таблица имеет 10k recs) join, со сложным предложением WHERE(например, функции или вычисления). Если вы поместите критерии фильтрации в предложение ON, соединения между этими 10 таблицами не произойдет, где предложение не будет выполнено вообще. В этом случае вы не выполняете 10000^10 вычислений в предложении WHERE. Это имеет смысл, не помещая параметры фильтрации только в предложение WHERE.