В SQL, Какая разница, условие ON после присоединения vs в конце нескольких JOINS
Мне было трудно найти ответ на этот вопрос, но...
может кто-то объяснить мне разницу между установкой условия ON JOIN с самим JOIN и установкой ON в конце всех остальных JOIN.
вот пример http://sqlfiddle.com/#!3/e0a0f/3
CREATE TABLE TableA (Email VARCHAR(100), SomeNameA VARCHAR(100))
CREATE TABLE Tableb (Email VARCHAR(100), SomeNameB VARCHAR(100))
CREATE TABLE Tablec (Email VARCHAR(100), SomeNameC VARCHAR(100))
INSERT INTO TableA SELECT '[email protected]', 'JoeA'
INSERT INTO TableA SELECT '[email protected]', 'JaneA'
INSERT INTO TableA SELECT '[email protected]', 'DaveA'
INSERT INTO TableB SELECT '[email protected]', 'JoeB'
INSERT INTO TableB SELECT '[email protected]', 'DaveB'
INSERT INTO TableC SELECT '[email protected]', 'JoeC'
INSERT INTO TableC SELECT '[email protected]', 'DaveC'
SELECT TOP 2 a.*,
b.*,
c.*
FROM TableA a
LEFT OUTER JOIN TableB b
ON a.email = b.email
INNER JOIN TableC c
ON c.Email = b.email;
SELECT TOP 2 a.*,
b.*,
c.*
FROM TableA a
LEFT OUTER JOIN TableB b
INNER JOIN TableC c
ON c.Email = b.email
ON a.email = b.email;
Я не понимаю, почему эти два оператора SELECT создают разные результаты.
Ответы
Ответ 1
Что важно, так это порядки объединений. Рассматривайте свои выражения так, как будто каждое соединение создает временную "виртуальную" таблицу.
Итак, когда вы пишете
FROM TableA a
LEFT OUTER JOIN TableB b ON a.email = b.email
INNER JOIN TableC c ON c.Email = b.email ;
тогда порядок выглядит следующим образом:
-
TableA
остается соединенным с TableB
, создающим временное отношение V1
-
V1
внутренне соединен с TableC
.
Значит, когда вы пишете:
FROM TableA a
LEFT OUTER JOIN TableB b
INNER JOIN TableC c ON c.Email = b.email ON a.email = b.email;
тогда порядок выглядит следующим образом:
-
TableB
внутренне соединен с TableC
, создавая временное отношение V1
.
-
TableA
остается соединенным с V1
.
Таким образом, результаты разные. Как правило, рекомендуется использовать скобки в таких ситуациях для улучшения читаемости запроса:
FROM TableA a
LEFT OUTER JOIN
(TableB b INNER JOIN TableC c ON c.Email = b.email)
ON a.email = b.email;
Ответ 2
В вашем втором примере часть ON a.email = b.email
принадлежит LEFT JOIN
.
Если это так написано, это означает следующее:
INNER JOIN
TableC с TableB и LEFT OUTER JOIN
результат с TableA.
Результатом будут все строки из таблицы А, объединенные с этими строками из таблицы Б, которые также имеют запись в TableC.
Первый пример означает следующее:
LEFT OUTER JOIN
TableB с TableA и INNER JOIN
TableC с результатом. Это эквивалентно использованию INNER JOIN
для TableB.
Объяснение: Когда вы LEFT OUTER JOIN
TableA с TableB, вы получите все строки из таблицы A и для сопоставления строк в TableB вы также получите эти данные. В вашем результирующем наборе у вас будут строки с b.email
= NULL
, и теперь это будет INNER JOIN
ed с TableC. Пока в таблице C нет записи с email
= NULL
, вы получите результаты, которые вы наблюдали.