2 Правильное внешнее объединение в операторе SQL - PullRequest
1 голос
/ 15 июля 2010

У меня проблема с пониманием очень простого, но интересного запроса, касающегося двух правых внешних объединений с «непоследовательными» выражениями. Вот запрос:

select * from C 
right outer join A on A.F1 = C.F1 
right outer join B on B.F1 = C.F1;

Вот таблицы:

create table A ( F1 varchar(200)); 
create table B ( F1 varchar(200)); 
create table C ( F1 varchar(200));

Вот несколько строк:

insert into A values ('A'); 
insert into A values ('B');
insert into A values ('C');
insert into B values ('B'); 
insert into B values ('C');
insert into B values ('D');
insert into C values ('A'); 
insert into C values ('C'); 
insert into C values ('D');

Примечание: запрос select * из C правого внешнего соединения A в A.F1 = C.F1 правого внешнего соединения B в B.F1 = C.F1; оба выражения соединения относятся к таблице C.

Запрос возвращает (в столбцах, а затем в строках)

(NULL,NULL, B),(C, C, C).(NULL, **NULL**, D)

и я ожидал (в моем небольшом понимании SQL)

(NULL,NULL, B),(C, C, C),(NULL, **D**, D)

Какова логическая последовательность, в соответствии с которой SQL (проверенный на Microsoft SQL, а также MySQL) достигает этих значений.

В моей «последовательности выполнения» я сижу в таблице A со значениями A, null (для B), C, null (для D) и в таблице B, null (для A), B, C, D перед «продукт» объединяется с C (B, C, D).

Gawie PS: я протестировал это с использованием MySQL, а также Microsoft SQL 2008 ... с теми же результатами.

Ответы [ 4 ]

1 голос
/ 15 июля 2010

В таблице "A" нет значения D для присоединения, поэтому он возвращает NULL вместо ожидаемого D. Проще увидеть, когда вы определяете, из какой таблицы исходит значение через псевдоним столбца:

SELECT c.f1 AS c, a.f1 AS a, b.f1 AS b 
  FROM c 
RIGHT JOIN A on A.F1 = C.F1 
RIGHT JOIN B on B.F1 = C.F1
0 голосов
/ 15 июля 2010

C, A -> (A, A), (NULL, B), (C, C)

Затем правое объединение B (соответствует первому столбцу, поскольку объединение находится в B.F1 = C.F1):

C, A, B -> (NULL, NULL, B), (C, C, C), (NULL, NULL, D)

Здесь я заблудился ...

Почему C, A, B не равны (NULL, B, B) и т. Д.

для C, A для столбца B равно (NULL, B) правое внешнее соединение (NULL, B) с B должно давать (NULL, B, B) ... если только совпадение не отменено! C, A, B -> (NULL, B, B) (что, очевидно, неправильно - просто не совсем понятно, почему)

0 голосов
/ 15 июля 2010

Правые объединения оцениваются в порядке их появления (слева направо). Начнем с from C:

C        -->  (A), (C), (D)

Затем right join A, присоединяясь к A.F1 = C.F1:

C, A     -->  (A, A), (NULL, B), (C, C)

Тогда right join B (соответствует первому столбцу, поскольку объединение B.F1 = C.F1):

C, A, B  -->  (NULL, NULL, B), (C, C, C), (NULL, NULL, D)

Так как from C right join A не содержит D в первом столбце, right join B не соответствует, и добавляет строку, содержащую NULL для столбца из C и A, и D для столбца из B.

0 голосов
/ 15 июля 2010

Таблица A не содержит поля 'D', поэтому D не может появиться во втором столбце в наборе результатов, Гоуи.Полями в наборе результатов будут C.F1, A.F1, B.F1 (в том же порядке, в котором таблицы появляются в объединениях).

...