Left Outer Join с использованием знака + в Oracle 11g

Может ли кто-нибудь сказать мне, есть ли ниже 2 запроса - пример Left Outer Join или Right Outer Join?

Table Part:
Name         Null?       Type
PART_ID      NOT NULL    VARCHAR2(4)
SUPPLIER_ID              VARCHAR2(4)

PART_ID SUPPLIER_ID
P1      S1
P2      S2
P3  
P4  

Table Supplier:
Name            Null?     Type
SUPPLIER_ID NOT NULL      VARCHAR2(4)
SUPPLIER_NAME   NOT NULL  VARCHAR2(20)

SUPPLIER_ID  SUPPLIER_NAME
S1           Supplier#1
S2           Supplier#2
S3           Supplier#3

Отображение всех деталей независимо от того, поставлял ли их поставщик или нет:

SELECT P.Part_Id, S.Supplier_Name
FROM Part P, Supplier S
WHERE P.Supplier_Id = S.Supplier_Id (+)

SELECT P.Part_Id, S.Supplier_Name
FROM Part P, Supplier S
WHERE S.Supplier_Id (+) = P.Supplier_Id

Спасибо!

Ответ 1

TableA LEFT OUTER JOIN TableB эквивалентен TableB RIGHT OUTER JOIN Table A.

В Oracle (+) обозначает "необязательную" таблицу в JOIN. Итак, в вашем первом запросе это a P LEFT OUTER JOIN S. В вашем втором запросе это S RIGHT OUTER JOIN P. Они функционально эквивалентны.

В терминологии RIGHT или LEFT укажите, какая сторона соединения всегда имеет запись, а другая сторона может быть нулевой. Таким образом, в P LEFT OUTER JOIN S, P всегда будет иметь запись, потому что она на LEFT, но S может быть нулевой.

Подробнее см. этот пример с java2s.com.


Чтобы уточнить, я думаю, что я говорю, что терминология не имеет значения, поскольку она только там, чтобы помочь визуализировать. Важно то, что вы понимаете, как это работает.


ПРАВИЛЬНО против LEFT

Я видел некоторую путаницу в том, что важно при определении RIGHT vs LEFT в синтаксисе неявного соединения.

ВЛЕВОЕ ВЗАИМОДЕЙСТВИЕ

SELECT *
FROM A, B
WHERE A.column = B.column(+)

ПРАВИЛЬНАЯ ВСТРОЕННАЯ РАБОТА

SELECT *
FROM A, B
WHERE B.column(+) = A.column

Все, что я сделал, это swap-стороны терминов в предложении WHERE, но они по-прежнему функционально эквивалентны. (См. Выше в моем ответе для получения дополнительной информации об этом.) Размещение (+) определяет RIGHT или LEFT. (В частности, если (+) находится справа, это ЛЕВЫЙ ПРИСОЕДИНЕНИЕ. Если (+) находится слева, это ПРАВОЕ СОЕДИНЕНИЕ.)


Типы JOIN

Два стиля JOIN - это неявные JOIN и явные JOIN. Это разные стили написания JOINs, но они функционально эквивалентны.

См. этот вопрос SO.

Неявные JOINs просто перечисляют все таблицы вместе. Условия соединения указаны в предложении WHERE.

Неявный JOIN

SELECT *
FROM A, B
WHERE A.column = B.column(+)

Явные JOINs связывают условия соединения с конкретным включением таблицы вместо предложения WHERE.

Явный JOIN

SELECT *
FROM A
LEFT OUTER JOIN B ON A.column = B.column

Эти Неявные JOINs могут быть более трудными для чтения и понимания, и у них также есть несколько ограничений, поскольку условия соединения смешиваются в других условиях WHERE. Таким образом, неявные JOINs обычно рекомендуются в пользу явного синтаксиса.

Ответ 2

Эти два запроса выполняют OUTER JOIN. См. Ниже

Oracle рекомендует использовать синтаксис FROM FROM OUTER JOIN а не оператор объединения Oracle. Запросы внешнего соединения, которые используют Оператор объединения Oracle (+) подчиняется следующим правилам и ограничения, которые не применяются к предложению FROM OUTER JOIN Синтаксис:

  • Вы не можете указать оператор (+) в блоке запроса, который также содержит синтаксис соединения предложения FROM.

  • Оператор (+) может отображаться только в предложении WHERE или, в контекст левой корреляции (при задании предложения ТАБЛИЦА) в FROM и может применяться только к столбцу таблицы или представления.

  • Если A и B соединены несколькими условиями соединения, вы должны использовать (+) во всех этих условиях. Если вы этого не сделаете, тогда Oracle Database вернет только строки, полученные в результате простого присоединяйтесь, но без предупреждения или ошибки, чтобы сообщить вам, что вы не имеют результаты внешнего соединения.

  • Оператор (+) не создает внешнее соединение, если вы укажете один таблицу во внешнем запросе и другую таблицу во внутреннем запросе.

  • Вы не можете использовать оператор (+) для внешней привязки таблицы к себе, хотя самосоединения действительны. Например, следующий оператор недействительно:

    -- The following statement is not valid:
    SELECT employee_id, manager_id
       FROM employees
       WHERE employees.manager_id(+) = employees.employee_id;
    

    Тем не менее, выполняется следующее самосоединение:

    SELECT e1.employee_id, e1.manager_id, e2.employee_id
       FROM employees e1, employees e2
       WHERE e1.manager_id(+) = e2.employee_id
       ORDER BY e1.employee_id, e1.manager_id, e2.employee_id;
    
  • Оператор (+) может применяться только к столбцу, а не произвольному выражение. Однако произвольное выражение может содержать одно или больше столбцов, помеченных оператором (+).

  • Условие WHERE, содержащее оператор (+), нельзя комбинировать с другое условие, использующее логический оператор ИЛИ.

  • Условие WHERE не может использовать условие сравнения IN для сравнения столбец, помеченный оператором (+) с выражением.

Если предложение WHERE содержит условие, которое сравнивает столбец от таблицу B с константой, то оператор (+) должен быть применен к чтобы Oracle возвращал строки из таблицы A, для которой он порожденных нулей для этого столбца. В противном случае Oracle возвращает только результаты простого соединения.

В запросе, который выполняет внешние объединения более двух пар таблиц, единственной таблицей может быть таблица, генерирующая нуль, только для одной Таблица. По этой причине вы не можете применить оператор (+) к столбцам B в условии соединения для A и B и условия соединения для B и C. Обратитесь к SELECT для синтаксиса внешнего соединения.

Взято из http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/queries006.htm

Ответ 3

Я видел некоторые противоречия в ответах выше, я просто попробовал следующее в Oracle 12c, и верно следующее:

ВЛЕВОЕ ВЗАИМОДЕЙСТВИЕ

SELECT *
FROM A, B
WHERE A.column = B.column(+)

ПРАВИЛЬНАЯ ВСТРОЕННАЯ РАБОТА

SELECT *
FROM A, B
WHERE B.column(+) = A.column

Ответ 4

В этом потоке есть некорректная информация. Я скопировал и вставил неверную информацию:

ВЛЕВОЕ ВЗАИМОДЕЙСТВИЕ

SELECT *
FROM A, B
WHERE A.column = B.column(+)

ПРАВИЛЬНАЯ ВСТРОЕННАЯ РАБОТА

SELECT *
FROM A, B
WHERE B.column(+) = A.column

Вышесказанное НЕПРАВИЛЬНО!!!!! Это изменилось. Как я определил это неверно из следующей книги:

Oracle OCP Введение в Oracle 9i: Руководство по экзамену SQL. В таблице 3-1 есть хорошее резюме по этому вопросу. Я не мог понять, почему мой преобразованный SQL не работал должным образом, пока я не пошел в старую школу и не посмотрел в печатную книгу!

Вот краткое изложение этой книги, скопированное по строкам:

Внешний синтаксис Oracle External:

from tab_a a, tab_b b,                                       
where a.col_1 + = b.col_1                                     

ANSI/ISO Эквивалент:

from tab_a a left outer join  
tab_b b on a.col_1 = b.col_1

Обратите внимание, что это обратное тому, что выложено выше. Я полагаю, что эта книга может иметь ошибки, но я больше доверяю этой книге, чем тому, что есть в этой теме. Это учебное пособие для крика вслух...