В 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, вы получите результаты, которые вы наблюдали.