Есть ли разница между этими двумя левыми соединениями в Oracle SQL?и почему - PullRequest
3 голосов
/ 29 февраля 2012
SELECT * 
FROM TAB1 
LEFT JOIN TAB2 ON TAB2.ID_TAB1 = TAB1.ID 
JOIN TAB3 ON TAB3.ID = TAB2.ID_TAB3;

и

SELECT *
FROM TAB1
LEFT JOIN (SELECT *
           FROM TAB2
           JOIN TAB3 ON TAB3.ID = TAB2.ID_TAB3) T
ON T.ID_TAB1 = TAB1.ID;

Ответы [ 2 ]

9 голосов
/ 29 февраля 2012

Нет, они разные - внутреннее соединение с TAB3 ( после левого соединения с TAB2) в первом запросе фактически превращает левое соединение во внутреннее соединение.

Скобки во втором запросе гарантируют, что внутреннее соединение с TAB3 оценивается перед левым соединением - поэтому оно остается левым соединением с TAB2, возвращая только те записи TAB2, где существует соответствующая запись TAB3 (в противном случае записи TAB1 возвращаются с соответствующими значениями NULL).

2 голосов
/ 29 февраля 2012

Что вам может понадобиться:

SELECT * 
FROM TAB1 
LEFT JOIN TAB2
JOIN TAB3
 ON TAB3.ID = TAB2.ID_TAB3
 ON TAB2.ID_TAB1 = TAB1.ID; 

В вашем первом запросе после того, как у вас есть LEFT JOIN и ассоциированное с ним предложение ON, то следующий JOIN (любого рода) будетпротив этого всего построенного потенциального набора результатов (то есть уже соединенных TAB2 и TAB1).И это следующее соединение, являющееся INNER JOIN, должно быть полностью удовлетворено для завершения соединения.

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


Просто нужно загрузить, установить Oracle Express.Этот скрипт:

CREATE TABLE TAB1 (
    ID int not null
);
CREATE TABLE TAB2 (
    ID_TAB1 int not null,
    ID_TAB3 int not null
);
CREATE TABLE TAB3 (
    ID int not null
);
INSERT INTO TAB1 (ID) VALUES (1);
INSERT INTO TAB1 (ID) VALUES (2);
INSERT INTO TAB3 (ID) VALUES (1);
INSERT INTO TAB3 (ID) VALUES (2);
INSERT INTO TAB2 (ID_TAB1,ID_TAB3) VALUES (2,2);
SELECT * 
FROM TAB1 
LEFT JOIN TAB2
JOIN TAB3
 ON TAB3.ID = TAB2.ID_TAB3
 ON TAB2.ID_TAB1 = TAB1.ID;

Сработал и запустился, как и ожидалось.


Может быть проще подумать о том, что делает этот запрос, если вы думаете, что JOIN вводит левыйскобки ( и ON, вводящие правую скобку ).Затем JOIN s и ON сопоставляются так же, как обычно сопоставляются круглые скобки.

Или, другими способами, можно считать, что каждое предложение join является "открытым" до тех пор, пока оно не будет соответствующимON встречается.Но правило для сопоставления ON с JOIN заключается в нахождении ближайшего «открытого» * ​​1034 *.

В любом случае, в приведенном выше запросе первое предложение ON удовлетворяет объединению междуTAB2 и TAB3.Второе предложение ON тогда удовлетворяет LEFT JOIN между TAB1 и объединенным (TAB2 и TAB3).

...