Left Outer Join mit + in Oracle 11g anmelden

80

Kann mir jemand sagen, ob die folgenden 2 Abfragen ein Beispiel für Left Outer Join oder Right Outer Join sind?

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

Zeigen Sie alle Teile an, unabhängig davon, ob ein Lieferant sie liefert oder nicht:

SELECT P.Part_Id, S.Supplier_Name
AB Teil P, Lieferant S.
WO P.Supplier_Id = S.Supplier_Id (+)

SELECT P.Part_Id, S.Supplier_Name
AB Teil P, Lieferant S.
WHERE S.Supplier_Id (+) = P.Supplier_Id
Mike
quelle
26
Sie sollten die Verwendung der Notation '(+)' vermeiden und die Abfragen aktualisieren, um explizite Verknüpfungen zu verwenden.
Jonathan Leffler
1
@ JonathanLeffler 100% zustimmen. Das Problem ist, dass ich mit Leuten zusammenarbeite, die nicht zur Standardnotation wechseln wollen. Ich schreibe eine neue Abfrage mit Standardnotation, aber ich werde in einer Minute schießen, wenn eine alte geändert wird.
Luc M
3
@ JonathanLeffler Ich würde zustimmen, es sei denn, Sie verwenden Oracle. Oracle verarbeitet derzeit nicht die Ansi-Syntax sowie den (+) - Operator intern. Obwohl sie empfehlen, die Ansi-Syntax zu verwenden :) docs.oracle.com/cd/B28359_01/server.111/b28286/queries006.htm
Ein Mythos
7
@Amyth Entschuldigung für diesen veralteten Kommentar, aber ich bin auf diese Frage von einer Suche gekommen. Ich selbst verstehe die Empfehlungen von Oracle genau umgekehrt. Über Ihren Link: " Oracle empfiehlt, dass Sie die FROM-Klausel OUTER JOIN-Syntax anstelle des Oracle-Join-Operators verwenden. Äußere Join-Abfragen, die den Oracle-Join-Operator (+) verwenden, unterliegen den folgenden Regeln und Einschränkungen, die für die nicht gelten FROM Klausel OUTER JOIN Syntax ... "
Sylvain Leroux
Entschuldigen Sie auch die veraltete Antwort :), aber was Oracle sagt und wie seine Statistiken zur Optimierung der Abfragen funktionieren, sind zwei verschiedene Dinge, und es könnte sein, dass Oracle seine Haltung mit den Fortschritten bei seinen internen Optimierern ebenfalls geändert hat
Ein Mythos

Antworten:

186

TableA LEFT OUTER JOIN TableBist äquivalent zu TableB RIGHT OUTER JOIN Table A.

(+)Bezeichnet in Oracle die "optionale" Tabelle in JOIN. In Ihrer ersten Abfrage ist es also a P LEFT OUTER JOIN S. In Ihrer zweiten Abfrage ist es S RIGHT OUTER JOIN P. Sie sind funktional gleichwertig.

In der Terminologie geben RECHTS oder LINKS an, auf welcher Seite des Joins immer ein Datensatz vorhanden ist, und die andere Seite ist möglicherweise null. Also in einem P LEFT OUTER JOIN S, Pwird immer ein Datensatz haben, weil es auf dem ist LEFT, aber Skönnte null sein.

Weitere Erklärungen finden Sie in diesem Beispiel von java2s.com .


Zur Verdeutlichung denke ich, dass Terminologie keine Rolle spielt, da sie nur zur Visualisierung dient. Was zählt, ist, dass Sie das Konzept verstehen, wie es funktioniert.


RECHTS gegen LINKS

Ich habe einige Verwirrung darüber gesehen, worauf es bei der Bestimmung von RIGHT vs LEFT in der impliziten Join-Syntax ankommt.

LINKE ÄUSSERE VERBINDUNG

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

RIGHT OUTER JOIN

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

Ich habe nur die Seiten der Begriffe in der WHERE-Klausel ausgetauscht, aber sie sind immer noch funktional gleichwertig. (Weitere Informationen hierzu finden Sie weiter oben in meiner Antwort.) Die Platzierung des (+)bestimmt RECHTS oder LINKS. (Insbesondere wenn (+)sich das rechts befindet, ist es ein LEFT JOIN. Wenn (+)es sich links befindet, ist es ein RIGHT JOIN.)


Arten von JOIN

Die beiden Stile von JOIN sind implizite JOINs und explizite JOINs . Sie sind verschiedene Arten des Schreibens von JOINs, aber sie sind funktional gleichwertig.

Siehe diese SO-Frage .

Implizite JOINs listen einfach alle Tabellen zusammen auf. Die Join-Bedingungen werden in einer WHERE-Klausel angegeben.

Implizite JOIN

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

Explizite JOINs verknüpfen Verknüpfungsbedingungen mit der Aufnahme einer bestimmten Tabelle anstelle einer WHERE-Klausel.

Explizite JOIN

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

Diese impliziten JOINs können schwieriger zu lesen und zu verstehen sein und sie haben auch einige Einschränkungen, da die Join-Bedingungen in anderen WHERE-Bedingungen gemischt sind. Daher werden implizite JOINs im Allgemeinen zugunsten einer expliziten Syntax empfohlen.

Schlaumeier
quelle
3
Richtig, ich verstehe es jetzt - der JOIN wird implizit durch das Vorhandensein des (+) erstellt. Cool.
Kerrek SB
2
@ Mike: So funktioniert die + -Syntax. Es bedeutet "optional", lesen Sie es also wie "Alle Teile auflisten, optional den Lieferanten anpassen".
Kerrek SB
2
@ Mike: Solange du weißt, was du auswählst, spielt es keine Rolle, wie du es nennst. Aber tun Sie sich selbst einen Gefallen und verwenden Sie JOINstattdessen die idiomatische Syntax! Dann gibt es keinen Raum für Verwirrung.
Kerrek SB
1
@TomJMuthirenthi Ohne explizite FULL OUTER JOINSyntax müssen Sie UNION [ALL]zwei Ergebnismengen zusammen verwenden: eine für A = B (+) und eine für B = A (+). Beispiel in dieser Frage .
Wiseguy
1
Das "(+)" steht in den Spalten der Tabelle, die Unterzeilen von Nullen generiert.
Philipxy
9

Diese beiden Abfragen werden ausgeführt OUTER JOIN. Siehe unten

Oracle empfiehlt, dass Sie die FROM-Klausel OUTER JOIN-Syntax anstelle des Oracle-Join-Operators verwenden. Äußere Join-Abfragen, die den Oracle-Join-Operator (+) verwenden, unterliegen den folgenden Regeln und Einschränkungen, die für die OUTER JOIN-Syntax der FROM-Klausel nicht gelten:

  • Sie können den Operator (+) nicht in einem Abfrageblock angeben, der auch die Join-Syntax der FROM-Klausel enthält.

  • Der Operator (+) kann nur in der WHERE-Klausel oder im Kontext der Linkskorrelation (bei Angabe der TABLE-Klausel) in der FROM-Klausel erscheinen und nur auf eine Spalte einer Tabelle oder Ansicht angewendet werden.

  • Wenn A und B durch mehrere Verknüpfungsbedingungen verbunden sind, müssen Sie in all diesen Bedingungen den Operator (+) verwenden. Wenn Sie dies nicht tun, gibt Oracle Database nur die Zeilen zurück, die sich aus einem einfachen Join ergeben, jedoch ohne Warnung oder Fehler, um Sie darauf hinzuweisen, dass Sie nicht über die Ergebnisse eines äußeren Joins verfügen.

  • Der Operator (+) erzeugt keinen äußeren Join, wenn Sie eine Tabelle in der äußeren Abfrage und die andere Tabelle in einer inneren Abfrage angeben.

  • Sie können den Operator (+) nicht verwenden, um eine Tabelle mit sich selbst zu verknüpfen, obwohl Selbstverknüpfungen gültig sind. Die folgende Anweisung ist beispielsweise ungültig:

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

    Der folgende Self-Join ist jedoch gültig:

    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;
    
  • Der Operator (+) kann nur auf eine Spalte angewendet werden, nicht auf einen beliebigen Ausdruck. Ein beliebiger Ausdruck kann jedoch eine oder mehrere Spalten enthalten, die mit dem Operator (+) markiert sind.

  • Eine WHERE-Bedingung, die den Operator (+) enthält, kann mit dem logischen Operator OR nicht mit einer anderen Bedingung kombiniert werden.

  • Eine WHERE-Bedingung kann die IN-Vergleichsbedingung nicht verwenden, um eine mit dem Operator (+) markierte Spalte mit einem Ausdruck zu vergleichen.

Wenn die WHERE-Klausel eine Bedingung enthält, die eine Spalte aus Tabelle B mit einer Konstanten vergleicht, muss der Operator (+) auf die Spalte angewendet werden, damit Oracle die Zeilen aus Tabelle A zurückgibt, für die es für diese Spalte Nullen generiert hat. Andernfalls gibt Oracle nur die Ergebnisse eines einfachen Joins zurück.

In einer Abfrage, die äußere Verknüpfungen von mehr als zwei Tabellenpaaren ausführt, kann eine einzelne Tabelle die nullgenerierte Tabelle für nur eine andere Tabelle sein. Aus diesem Grund können Sie den Operator (+) nicht auf Spalten von B in der Verknüpfungsbedingung für A und B und der Verknüpfungsbedingung für B und C anwenden. Die Syntax für eine äußere Verknüpfung finden Sie unter SELECT.

Entnommen aus http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/queries006.htm

Rahul
quelle
2

Ich habe in den obigen Antworten einige Widersprüche gesehen. Ich habe gerade Folgendes unter Oracle 12c versucht und Folgendes ist richtig:

LINKE ÄUSSERE VERBINDUNG

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

RIGHT OUTER JOIN

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

LINKE ÄUSSERE VERBINDUNG

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

RIGHT OUTER JOIN

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

Rupasa Sushma
quelle
-2

Dieser Thread enthält einige falsche Informationen. Ich habe die falschen Informationen kopiert und eingefügt:

LINKE ÄUSSERE VERBINDUNG

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

RIGHT OUTER JOIN

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

Das obige ist FALSCH !!!!! Es ist umgekehrt. Wie ich festgestellt habe, dass es falsch ist, stammt aus dem folgenden Buch:

Oracle OCP Einführung in Oracle 9i: SQL Exam Guide . Seite 115 Tabelle 3-1 enthält eine gute Zusammenfassung. Ich konnte nicht herausfinden, warum mein konvertiertes SQL nicht richtig funktionierte, bis ich auf die alte Schule ging und in einem gedruckten Buch nachschaute!

Hier ist die Zusammenfassung aus diesem Buch, Zeile für Zeile kopiert:

Oracle Outer Join Syntax:

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

ANSI / ISO-Äquivalent:

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

Beachten Sie hier, dass es das Gegenteil von dem ist, was oben angegeben ist. Ich nehme an, es ist möglich, dass dieses Buch Errata enthält, aber ich vertraue diesem Buch mehr als dem, was in diesem Thread steht. Es ist ein Prüfungsleitfaden zum lauten Schreien ...

irgendwann
quelle
4
Dies widerspricht dem, worauf ich in meiner Antwort verwiesen habe, die ein Auszug aus der 1. Ausgabe von Oracle Database 10g SQL (Osborne ORACLE Press Series) (20. Februar 2004) ist und besagt: "In einem linken äußeren Join ist der Operator für den äußeren Join tatsächlich aktiviert das Recht des Gleichheitsoperators. " Hier ist eine Demo Ihres Beispiels . Die Ergebnisse der a.col_1(+) = b.col_1Übereinstimmung RIGHT JOIN, nicht LEFT JOIN.
Wiseguy