Join (SQL)

SQL-Anweisung zur Verknüpfung mehrerer Tabellen
Dies ist eine alte Version dieser Seite, zuletzt bearbeitet am 21. Dezember 2017 um 23:23 Uhr durch Hundsrose (Diskussion | Beiträge) (INNER JOIN). Sie kann sich erheblich von der aktuellen Version unterscheiden.
Dieser Importartikel ist fälschlicherweise im Artikelnamensraum. Bitte verschiebe die Seite oder entferne diesen Baustein.
Dieser Artikel (Join (SQL)) ist im Entstehen begriffen und noch nicht Bestandteil der freien Enzyklopädie Wikipedia.
Wenn du dies liest:
  • Der Text kann teilweise in einer Fremdsprache verfasst, unvollständig sein oder noch ungeprüfte Aussagen enthalten.
  • Wenn du Fragen zum Thema hast, nimm am besten Kontakt mit den Autoren auf.
Wenn du diesen Artikel überarbeitest:
  • Bitte denke daran, die Angaben im Artikel durch geeignete Quellen zu belegen und zu prüfen, ob er auch anderweitig den Richtlinien der Wikipedia entspricht (siehe Wikipedia:Artikel).
  • Nach erfolgter Übersetzung kannst du diese Vorlage entfernen und den Artikel in den Artikelnamensraum verschieben. Die entstehende Weiterleitung kannst du schnelllöschen lassen.
  • Importe inaktiver Accounts, die länger als drei Monate völlig unbearbeitet sind, werden gelöscht.

Ein SQL-Join verknüpft eine ode mehrere Spalten einer Relationalen Datenbank. Das Ergebnis kann als Tabelle ausgegeben oder weiterverarbeitet werden. Ein JOIN ermöglicht das Verknüpfen von Spalten einer einzelnen Tabelle (self-Tabelle) oder mehrere Tabellen welche identische Werte aufweisen. Der ANSI-Standard für SQL beschreibt fünf Arten von JOINs: INNER, LEFT OUTER, RIGHT OUTER, FULL OUTER und CROSS. Als Spezialfall kann eine Tabelle (Basistabelle, View oder joined Tabelle) ein Join auf sich selbst durchführen (SELF JOIN).

Ein Programmierer deklariert ein JOIN-Statement um mögliche Reihen für einen Join zu identifizieren. Falls das ermittelte Prädikat wahr ist, wird die verknüpfte Spalte in einem entsprechenden Format, einem Satz von Reihen oder einer temporären Tabelle wiedergegeben.

Referenz-Tabelle

Relationale Datenbanken sind für gewöhnlich normalisiert um Duplikate, wie sie bei Entitätstypen mit one-to-many-Verknüpfungen bestehen, zu eliminieren. Zum kann zum Beispiel eine Abteilung mit mehreren Angestellten verknüpft sein. Ein Join dieser beiden Tabellen ist eine effektive Möglichkeit um eine neue Tabelle zu erstellen, welche alle Informationen beider Tabellen enthält.

Alle nachfolgenden Erklärungen über die verschiedenen Arten von Joins verwenden die beiden weiter unten dargestellten Tabellen. Die Reihen dieser Tabellen dienen der Beschreibung der Wirkweise verschiedener Arten von Joins und deren Prädikate.

In den folgenden Tabellen ist die Spalte AbteilungID der Tabelle Abteilung (welche als Abteilung.AbteilungID bezeichnet werden kann) der Primärschlüssel, während Angestellter.AbteilungID der Fremdschlüssel ist.

Tabelle: Angestellter
Nachname AbteilungID
Müller 31
Schmidt 33
Schneider 33
Fischer 34
Weber 34
Meyer NULL
Tabelle: Abteilung
AbteilungID AbteilungName
31 Verkauf
33 Technik
34 Buero
35 Marketing

Anmerkung: In der obigen Tabelle Angestellter wurde dem Angestellten "Meyer" noch keine Abteilung zugewiesen. Außerdem, sollte beachtet werden, dass bisher kein Angestellter der Abteilung "Marketing" zugewiesen worden ist.

Dies ist das SQL-Statement um die zuvor genannten Tabellen zu erzeugen.

CREATE TABLE Abteilung
(
 AbteilungID INT Primary key,
 AbteilungName VARCHAR(20)
);

CREATE TABLE Angestellter
(
 Nachname VARCHAR(20),
 AbteilungID INT references Abteilung(AbteilungID)
);

INSERT INTO Abteilung VALUES(31, 'Verkauf');
INSERT INTO Abteilung VALUES(33, 'Technik');
INSERT INTO Abteilung VALUES(34, 'Buero');
INSERT INTO Abteilung VALUES(35, 'Marketing');

INSERT INTO Angestellter VALUES('Müller', 31);
INSERT INTO Angestellter VALUES('Schmidt', 33);
INSERT INTO Angestellter VALUES('Schneider', 33);
INSERT INTO Angestellter VALUES('Fischer', 34);
INSERT INTO Angestellter VALUES('Weber', 34);
INSERT INTO Angestellter VALUES('Meyer', NULL);

CROSS JOIN

Ein CROSS JOIN gibt das Kartesisches Produkt der Tabellenreihen eines Joins wieder. Mit anderen Worten, ein Join erstellt Reihen welche jede Reihe der einen Tabelle mit jeder Reihe der anderen Tabelle verknüpft. [1]

Beispiel eines expliziten CROSS JOINs:

SELECT *
FROM Angestellter <code>CROSS JOIN</code> Abteilung;

Beispiel eines impliziten CROSS JOINs:

SELECT *
FROM Angestellter, Abteilung;
Angestellter.Nachname Angestellter.AbteilungID Abteilung.AbteilungName Abteilung.AbteilungID
Müller 31 Verkauf 31
Schmidt 33 Verkauf 31
Schneider 33 Verkauf 31
Weber 34 Verkauf 31
Fischer 34 Verkauf 31
Meyer NULL Verkauf 31
Müller 31 Technik 33
Schmidt 33 Technik 33
Schneider 33 Technik 33
Weber 34 Technik 33
Fischer 34 Technik 33
Meyer NULL Technik 33
Müller 31 Buero 34
Schmidt 33 Buero 34
Schneider 33 Buero 34
Weber 34 Buero 34
Fischer 34 Buero 34
Meyer NULL Buero 34
Müller 31 Marketing 35
Schmidt 33 Marketing 35
Schneider 33 Marketing 35
Weber 34 Marketing 35
Fischer 34 Marketing 35
Meyer NULL Marketing 35

Ein CROSS JOIN verwendet kein Prädikat um die Reihen der gejointen Tabelle zu filtern. Das Resultat eines CROSS JOINs kann durch eine WHERE-Clause gefiltert werden, was wiederum einem INNER JOIN entsprechen kann.

Im SQL:2011-Standard werden CROSS JOINs als Teil des optionalen F401-Pakets "Extended joined table" aufgelistet.

Ein typischer Einsatz sind Checks der Leistungsfähigkeit von Servern.

INNER JOIN

 
Venn Diagram: INNER JOIN zweier Tabellen A und B

Für einen INNER JOIN müssen in jeder Zeile der zwei gejointen Tabellen übereinstimmende Spalten-Werte vorhanden sein. Diese Join-Operation wird in Software sehr oft verwendet, sollte aber nicht als beste Lösung für alle Problemstellungen gesehen werden. Ein INNER JOIN erstellt eine neue Ergebnis-Tabelle indem er die Spalten-Werte der zwei Tabellen A und B aufgrund ihres Join-Prädikats miteinander vebindet. Die Abfrage vergeleicht jede Zeile von Tabelle A mit jeder Zeile von Tabelle B um alle Paare zu finden, die dem Join-Prädikat genügen. Falls das Join-Prädikat keine NULL-Werte findet, werden die Spalten-Werte jedes übereinstimmenden Zeilenpaars von A und B in eine Ergebnis-Zeile vereinigt.

Das Ergebnis eines Joins entspricht einem Kartesischen Produkt (oder CROSS JOIN) aller Zeilen der Tabellen A und B (jede Zeile der Tabelle A mit jeder Zeile der Tabelle B) bei anschließender Ausgabe aller Zeilen welche dem Join-Prädikat genügen.

Gegenwärtige SQL-Umsetzungen verwenden für gewöhnlich Ansätze, wie z.B.: Hash Joins oder Sort-Merge Joins, da das Berechnen eines kartesischen Produkts viel langsamer wäre und viel Arbeitsspeicher benötigen würde.

SQL kennt zwei verschiedene syntaktische Werte Joins zu verwenden: die "explizite Join-Notation" und die "implizite Join-Notation". Die "implizite Join-Notation" wird nicht mehr als Best practice angesehen, wird jedoch von Datenbanksystemen weiterhin unterstützt. Die "explizite Join-Notation" verwendet das JOIN-Schlüsselwort, optional mit dem INNER-Schlüsselwort vorangestellt, um die Tabelle zu benennen und das ON-Schlüsselwort um das Join-Prädikat zu defnieren.

Beispiel für die explizite Join-Notation:

SELECT Angestellter.Nachname, Angestellter.AbteilungID, Abteilung.AbteilungName 
FROM Angestellter 
INNER JOIN Abteilung ON
Angestellter.AbteilungID = Abteilung.AbteilungID
Angestellter.Nachname Angestellter.AbteilungID Abteilung.AbteilungName
Fischer 34 Buero
Schmidt 33 Technik
Weber 34 Buero
Schneider 33 Technik
Müller 31 Verkauf

In der "impliziten" Join-Notation werden die zu joinenden Tabellen in der FROM-Clause der SELECT-Abfrage , lediglich durch ein Komma getrennt, genannt. Dadurch wird ein CROSS JOIN durchgeführt und auf die WHERE-Clause kann weitere Filter-Prädikate angewandt werden, welche vergleichbar zu den Join-Prädikaten der expliziten Join-Notation funktionieren. Das folgende Beispiel ist äquivalent zum vorherigen, dieses Mal wird jedoch die implizite Join-Notation verwendet:


SELECT *
FROM Angestellter, Abteilung
WHERE Angestellter.AbteilungID = Abteilung.AbteilungID;

Die Abfragen der obigen Beispiele joinen die Tabellen Angestellter und Abteilung indem sie die gemeinsame Spalte AbteilungID verwenden. In den Fällen in denen AbteilungID dieser Tabellen passen (also das Join-Prädikat erfüllt ist) wird die Abfrage die Spalten Nachname, AbteilungID und AbteilungName der beiden Tabellen zu einer Ergebnis-Zeile verbinden. Sollte AbteilungID nicht passen, wird keine Ergebnis-Zeile generiert. Das Ergebnis des Auswertungsplans der Abfrage sieht folgendermaßen aus:

Angestellter.Nachname Angestellter.AbteilungID Abteilung.AbteilungName Abteilung.AbteilungID
Fischer 34 Buero 34
Schmidt 33 Technik 33
Weber 34 Buero 34
Schneider 33 Technik 33
Müller 31 Verkauf 31

Der Angestelle "Meyer" und die Abteilung "Marketing" tauchen nach der Ausführung der Abfrage nicht als Ergebnisse auf. Keiner von beiden weist eine passende Zeile in der entsprechend anderen Tabelle auf: "Meyer" hat keine entsprechende Abteilung und kein Angestellter hat die AbteilungId 35 ("Marketing"). Abhängig von den gewünschten Resultaten, kann dieses Verhalten als simpler Bug gesehen werden, welcher durch das Ersetzen von INNER JOIN durch OUTER JOIN, gefixt werden kann.

Bei einem Join zweier Tabellen, welche NULL-Werte enthalten, ist besondere Vorsicht angebracht. In diesem Fall wird kein NULL-Wert mit einem anderen Wert übereinstimmen (auch nicht mit dem NULL-Wert selbst). Diese Einträge können jedoch durch die explizite Verwendung eines modifizierten Prädikats in der Join-Bedingung berücksichtigt werden. Dabei wird zunächst überprüft, ob die Join-Spalten den Wert NOT NULL aufweisen, bevor die restlichen Prädikatsbedingungen angewandt werden.

Der INNER JOIN kann nur bedenkenlos in Datenbanken verwendet werden, welche Referentielle Integrität erzwingen oder in Fällen in denen die Join-Spalten mit Sicherheit nicht NULL sind. Viele transaktionsverarbeitende relationale Datenbanken basieren auf dem ACID-Prinzip-Standards für Datenupdates um die Datenintegrität zu gewährleisten wodurch INNER JOINs eine gute Wahl sind. Transaktionsdatenbanken haben jedoch meist erwünschte Join-Spalten, die NULL-Werte enthalten können. Manche report-erstellende relationale Datenbanken und Data-Warehouses verwenden Batch-Updates für ETL-Prozesse, welche den Zwang zur Erhaltung der referentiellen Integrität schwierig oder unmöglich machen, wodurch Join-Spalten mit NULL-Werten entstehen können, welche der Autor der SQL-Abfrage nicht verändern kann und welche bei einem INNER JOINs zu einem Verlust von Datensätzen führen kann ohne dass es Anzeichen für Fehler gibt. Die Entscheidung für oder gegen einen INNER JOIN hängt vom Design der Datenbank und den Besonderheiten der Datensätze ab. Ein LEFT OUTER JOIN kann für gewöhnlich durch einen INNER JOIN ersetzt werden, sofern die Join-Spalten in einer Tabelle NULL-Werte enthalten.

Spalten mit Datensätzen die NULL-Werte enthalten sollten nie als Verknüpfung in einem INNER JOIN verwendet werden, außer Spalten mit NULL-Werten sollen entfernt werden. In diesem Fall kann ein INNER JOIN sogar schneller als ein OUTER JOIN sein, da der Join und das Filtern in einem einzigen Schritt abgearbeitet werden. Anderseits kann ein INNER JOIN verheerend langsame Performance oder sogar einen Serverabsturz zur Folge haben, falls dieser in einer hochvolumigen Abfrage in Kombination mit Datenbankfunktionen in einer WHERE-Bedingung ausgeführt wird.[2][3][4]

Eine Funktion in einer WHERE-Bedingung kann dazu führen, dass eine Datenbank relativ kompakte Tabellenindizes ignoriert. Unter Umständen liest die Datenbank die ausgewählten Spalten der beiden Tabellen aus und führt einen INNER JOIN mit ihnen aus, bevor die Anzahl der Zeilen durch den Filter, welcher von einem vorher berechneten Wert abhängt, reduziert werden können. Dies führt schließlich zu einer relativ ineffizienten Prozessverarbeitung.

Sollte ein Ergebnis-Set durch einen Join mehrerer Tabellen produziert werden, welche Master-Tabellen enthalten, die verwendet werden um ganze Text-Beschreibungen numerischer Kennzahlen nachzuschlagen ( Lookup-Tabelle), kann ein NULL-Wert in einem der Sekundärschlüssel eine Löschung der gesamten Zeile aus dem Ergebnis-Set verursachen ohne dass ein Hinweis auf einen Fehler angezeigt wird. Eine komplexe SQL-Abfrage, welche eine oder mehrere INNER JOINs und mehrere OUTER JOINs enthält, birgt das gleiche Risiko für NULL-Werte in den verknüpften Spalten des INNER JOINs. Ein Commit für SQL-Code welche NULL-Werte von INNER JOINs berücksichtigt ist in zukünftigen Änderungen also Updates von Anbietern, Veränderungen am Design, Stapelverarbeitung außerhalb der Regeln der Datenvalidierung der Anwendung (wie Datenkonvertierung), Migrationen, Bulk-Importe und Merges, nicht vorgesehen.

Ein INNER JOINs kann außerdem als EQUI JOIN, als NATURAL JOIN oder als CROSS JOIN klassifiziert werden.

EQUI JOIN

Ein EQUI JOIN ist ein vergleichsbasierter Join, welcher nur den Gleichheits-Vergleich im Join-Prädikat verwendet. Werden andere Vergleichsoperatoren (wie z.B.: <) verwendet, handelt es sich nicht um einen EQUI JOIN. Die obige Abfrage enthält bereits ein Beispiel für einen EQUI JOIN:

SELECT *
FROM Angestellter JOIN Abteilung
  ON Angestellter.AbteilungID = Abteilung.AbteilungID;

Der EQUI JOIN kann wie folgt geschrieben werden:

SELECT *
FROM Angestellter, Abteilung
WHERE Angestellter.AbteilungID = Abteilung.AbteilungID;

Der SQL-92-Standard liefert eine optionale Kurznotation um Spalten gleichen Namens mit dem USING-Konstrukt zu beschreiben:[5]

SELECT *
FROM Angestellter <code>INNER JOIN</code> Abteilung USING (AbteilungID);

Das USING-Konstrukt ist mehr als nur Syntaktischer Zucker, da das Resultat sich von der Abfrage mit explizitem Prädikat unterscheidet. Alle in der USING-Liste enthaltenen Spalten werden mit einem unbestimmten Namen statt je einem für jede Tabelle des Joins angezeigt. Das obige Beispiel ergibt eine einzelne Spalte AbteilungID und keine Angestellter.AbteilungID- oder Abteilung.AbteilungID-Spalte.

Die USING-Clause wird nicht von MS SQL Server und Sybase unterstützt.

NATURAL JOIN

Der NATURAL JOIN ist ein Spezialfall des EQUI JOINs. Der NATURAL JOIN (⋈)ist eine Zweistellige Relation, welche in der Form RS (mit R und S als Relationen) geschrieben werden kann. In Unicode wird die Fliege ⋈ mit dem Zahlencode U+22C8 dargestellt. Das Ergebnis eines NATURAL JOINs ist das Set aller Tupel-Kombinationen von R und S, welche identische Namensattribute besitzen. Das folgende Beispiel verdeutlicht den NATURAL JOIN anhand der Tabellen Angestellter und Abteilung:

Angestellter
Name AngID AbtName
Ben 3415 Finanzen
Mia 2241 Verkauf
Paul 3401 Finanzen
Emma 2202 Verkauf
Abteilung
AbtName Manager
Finanzen Paul
Verkauf Emma
Production Charles
Angestellter   Abteilung
Name AngID AbtName Manager
Ben 3415 Finanzen Paul
Mia 2241 Verkauf Emma
Paul 3401 Finanzen Paul
Emma 2202 Verkauf Emma

This can also be used to define Relations-Verknüpfung. For example, the composition of Angestellter and Abteilung is their join as shown above, projected on all but the common attribute AbtName. In Kategorientheorie, the join is precisely the Faserprodukt.

The NATURAL JOIN is arguably one of the most important operators since it is the relational counterpart of logical AND. Note that if the same variable appears in each of two predicates that are connected by AND, then that variable stands for the same thing and both appearances must always be substituted by the same value. In particular, the NATURAL JOIN allows the combination of relations that are associated by a Fremdschlüssel. For example, in the above example a foreign key probably holds from Angestellter.AbtName to Abteilung.AbtName and then the NATURAL JOIN of Angestellter and Abt combines all Angestellters with their Abteilungs. This works because the foreign key holds between attributes with the same name. If this is not the case such as in the foreign key from Abt.manager to Angestellter.Name then these columns have to be renamed before the NATURAL JOIN is taken. Such a join is sometimes also referred to as an EQUI JOIN.

More formally the semantics of the NATURAL JOIN are defined as follows:

 ,

where Fun is a Prädikat that is true for a Relation r If and only if r is a function. It is usually required that R and S must have at least one common attribute, but if this constraint is omitted, and R and S have no common attributes, then the NATURAL JOIN becomes exactly the Cartesian product.

The NATURAL JOIN can be simulated with Codd's primitives as follows. Let c1, …, cm be the attribute names common to R and S, 'r1, …, rn be the attribute names unique to R and let s1, …, sk be the attributes unique to S. Furthermore, assume that the attribute names x1, …, xm are neither in R nor in S. In a first step the common attribute names in S can now be renamed:

 

Then we take the Cartesian product and select the tuples that are to be joined:

 

A NATURAL JOIN is a type of EQUI JOIN where the join predicate arises implicitly by comparing all columns in both tables that have the same column-names in the joined tables. The resulting joined table contains only one column for each pair of equally named columns. In the case that no columns with the same names are found, the result is a [[#CROSS JOIN|CROSS JOIN]].

Most experts agree that NATURAL JOINs are dangerous and therefore strongly discourage their use.[6] The danger comes from inadvertently adding a new column, named the same as another column in the other table. An existing NATURAL JOIN might then "naturally" use the new column for comparisons, making comparisons/matches using different criteria (from different columns) than before. Thus an existing query could produce different results, even though the data in the tables have not been changed, but only augmented. The use of column names to automatically determine table links is not an option in large databases with hundreds or thousands of tables where it would place an unrealistic constraint on naming conventions. Real world databases are commonly designed with Fremdschlüssel data that is not consistently populated (NULL values are allowed), due to business rules and context. It is common practice to modify column names of similar data in different tables and this lack of rigid consistency relegates NATURAL JOINs to a theoretical concept for discussion.

The above sample query for INNER JOINs can be expressed as a NATURAL JOIN in the following way:

SELECT *
FROM Angestellter NATURAL JOIN Abteilung;

As with the explicit USING clause, only one AbteilungID column occurs in the joined table, with no qualifier:

AbteilungID Angestellter.Nachname Abteilung.AbteilungName
34 Weber Buero
33 Schmidt Technik
34 Fischer Buero
33 Schneider Technik
31 Müller Verkauf

PostgreSQL, MySQL and Oracle support NATURAL JOINs; Microsoft T-SQL and IBM DB2 do not. The columns used in the join are implicit so the join code does not show which columns are expected, and a change in column names may change the results. In the SQL:2011 standard, NATURAL JOINs are part of the optional F401, "Extended joined table", package.

In many database environments the column names are controlled by an outside vendor, not the query developer. A NATURAL JOIN assumes stability and consistency in column names which can change during vendor mandated version upgrades.

OUTER JOIN

Die gejointe Tabelle enthält jede Zeile, selbst wenn diese keine Paare bilden. OUTER JOINs werden außerdem in LEFT OUTER-Joins, RIGHT OUTER-Joins und FULL OUTER-Joins unterteilt. Das Kriterium ist hierfür, welche Zeilen der Tabellen erhalten bleiben. Die Ausdrücke LEFT, RIGHT and FULL stehen für die rechte, linke oder beide Seite(n) des JOIN-Schlüsselworts.

Im SQL-Standard ist keine implizite Join-Notation für OUTER JOINs vorgesehen.


LEFT OUTER JOIN

 
Venn-Diagramm: LEFT JOIN zweier Tabellen A und B.

Das Ergebnis eines LEFT OUTER JOINs (oder vereinfacht LEFT JOIN) der Tabellen A und B enthält alle Zeilen der linken ("LEFT") Tabelle A, selbst wenn die Join-Bedingung auf keine Spalte der rechten ("RIGHT") Tabelle B zutrifft.

Falls die ON-Clause für eine vorgegebene Zeile der Spalte A keine Zeile für die Tabelle B liefert, wird der Join trotzdem die Zeile der Spalte A ausgeben. Die entsprechenden Einträge für die Spalten der Tabelle B sind jedoch mit dem NULL-Wert ausgegeben. Ein LEFT OUTER JOIN gibt alle Werte eines INNER JOINs wieder zusätzlich aller Werte einer LEFT-Tabelle, welche nicht der RIGHT-Tabelle entsprechen und alle Zeilen mit NULL-Werten (also leeren Werten) der linken Spalte.

Wir können nun die Abteilung eines jeden Angestellten finden und trotzdem diejenigen Angestellten auflisten, welche noch keiner Abteilung zugewiesen worden sind (im Gegensatz zum INNER JOIN-Beispiel vorher, bei dem diese Angestellten ausgeschlossen worden.)

Beispiel eines LEFT OUTER JOINs (das OUTER-Schlüsselwort ist optional) mit der zusätzlichen in kursiv geschriebenen Zeile (verglichen mit dem INNER JOIN):

SELECT *
FROM Angestellter 
LEFT OUTER JOIN Abteilung ON Angestellter.AbteilungID = Abteilung.AbteilungID;
Angestellter.Nachname Angestellter.AbteilungID Abteilung.AbteilungName Abteilung.AbteilungID
Schmidt 33 Technik 33
Müller 31 Verkauf 31
Fischer 34 Buero 34
Weber 34 Buero 34
Meyer NULL NULL NULL
Schneider 33 Technik 33

Alternative Syntax: Oracle unterstüt die veraltete [7] Sytax.

SELECT *
FROM Angestellter, Abteilung
WHERE Angestellter.AbteilungID = Abteilung.AbteilungID(+)

Sybase unterstützt die folgende Sytax (Microsoft SQL Server unterstützt diese Version seit 2000 nicht mehr):

SELECT *
FROM Angestellter, Abteilung
WHERE Angestellter.AbteilungID *= Abteilung.AbteilungID

IBM Informix unterstützt diese Syntax:

SELECT *
FROM Angestellter, OUTER Abteilung
WHERE Angestellter.AbteilungID = Abteilung.AbteilungID

RIGHT OUTER JOIN

 
Venn-Diagramm : RIGHT JOIN zweier Tabellen A and B.

Ein RIGHT OUTER JOIN (auch RIGHT JOIN) ähnelt stark einem LEFT OUTER JOIN, mit dem Unterschied, dass die Tabellen in umgekehrter Reihenfolge abgearbeitet werden. Jede Zeile der rechten ("RIGHT") Tabelle (B) wird in der gejointen Tabelle mindestens einmal vorkommen. Im Falle keiner passenden Zeile der linken ("LEFT") Tabelle (A) erscheint der NULL-Wert in den Spalten von A für die Reihen welche keine Entsprechung in B haben. Ein RIGHT OUTER JOIN gibt alle Werte der rechten ("RIGHT") Tabelle und passenden Werte der linken ("LEFT") Tabelle wieder (im Falle keiner passendenen Join-Prädikate NULL). Daher können wir zum Beispiel jeden Angestellten und seine oder seine Abteilung finden, aber dennoch Abteilungen anzeigen lassen, die keine Angestellten besitzen. Weiter unten ist ein Beispiel eines RIGHT OUTER JOINs ( das OUTER-Schlüsselwort ist optional) mit der Ergebniszeile in kursiver Schrift:

SELECT *
FROM Angestellter RIGHT OUTER JOIN Abteilung
  ON Angestellter.AbteilungID = Abteilung.AbteilungID;
Angestellter.Nachname Angestellter.AbteilungID Abteilung.AbteilungName Abteilung.AbteilungID
Weber 34 Buero 34
Schmidt 33 Technik 33
Fischer 34 Buero 34
Schneider 33 Technik 33
Müller 31 Verkauf 31
NULL NULL Marketing 35

RIGHT und LEFT OUTER JOIN sind funktional äquivalent. Keiner von beidem besitzt eine Funktionalität, welche der andere nicht hat. Sie können also sich gegenseitig ersetzen indem die Reihenfolge der Tabellen in der Abfrage vertauscht wird.

FULL OUTER JOIN

 
Venn-Diagramm: FULL JOIN zweier Tabellen A and B.

Ein FULL OUTER JOIN verbindet die Resultate eines LEFT und eines RIGHT OUTER JOINs. Nicht passende Zeileneinträge bei einem FULL OUTER JOINs werden mit NULL-Werten für jede Spalte der Tabelle versehen, denen eine passende Zeile fehlt. Für passende Zeilen wird eine einzelne Zeile im Ergebnis-Set erstellt, welche die Spalten beider Tabellen erhält. Zum Beispiel können wir dadurch jeden Angestellten anzeigen, welche einer Abteilung zugewiesen ist und jede Abteilung die einen Angestellten hat, aber zusätzlich auch Angestellte die nicht Teil einer Abteilung sind oder Abteilungen die keine Angestellten haben.

Beispiel für einen FULL OUTER JOIN (das OUTER-Schlüsselwort ist optional):

SELECT *
FROM Angestellter FULL OUTER JOIN Abteilung
  ON Angestellter.AbteilungID = Abteilung.AbteilungID;
Angestellter.Nachname Angestellter.AbteilungID Abteilung.AbteilungName Abteilung.AbteilungID
Weber 34 Buero 34
Schmidt 33 Technik 33
Fischer 34 Buero 34
Meyer NULL NULL NULL
Schneider 33 Technik 33
Müller 31 Verkauf 31
NULL NULL Marketing 35

Manche Datenbank-Systeme unterstützen die Funktionalität des FULL OUTER JOINs nicht direkt. Sie können diesen aber durch den Gebrauch eines INNER JOINs und eines UNION ALL imitieren, indem sie die alleinstehenden Zeilen der rechten ("RIGHT") und der linken ("LEFT") Tabelle, sowie den INNER JOIN mit einem UNION ALL verbinden. Das gleiche Beispiel sieht dann wie folgt aus:

SELECT Angestellter.Nachname, Angestellter.AbteilungID,
       Abteilung.AbteilungName, Abteilung.AbteilungID
FROM Angestellter
INNER JOIN Abteilung ON Angestellter.AbteilungID = Abteilung.AbteilungID

UNION ALL

SELECT Angestellter.Nachname, Angestellter.AbteilungID,
       cast(NULL as varchar(20)), cast(NULL as integer)
FROM Angestellter
WHERE NOT EXISTS (
    SELECT * FROM Abteilung
             WHERE Angestellter.AbteilungID = Abteilung.AbteilungID)

UNION ALL

SELECT cast(NULL as varchar(20)), cast(NULL as integer),
       Abteilung.AbteilungName, Abteilung.AbteilungID
FROM Abteilung
WHERE NOT EXISTS (
    SELECT * FROM Angestellter
             WHERE Angestellter.AbteilungID = Abteilung.AbteilungID)

Alternativen

Das Ergebnis eines OUTER JOINs kann auch mit einem UNION ALL zwischen einem INNER JOIN und einem SELECT der Zeilen der "Haupt"-Tabelle welche nicht die Join-Bedingung erfüllen, erreicht werden.

Zum Beispiel kann

SELECT Angestellter.Nachname, Angestellter.AbteilungID, Abteilung.AbteilungName
FROM Angestellter
LEFT OUTER JOIN Abteilung ON Angestellter.AbteilungID = Abteilung.AbteilungID;

auch auf diese Weise geschrieben werden:

SELECT Angestellter.Nachname, Angestellter.AbteilungID, Abteilung.AbteilungName
FROM Angestellter
INNER JOIN Abteilung ON Angestellter.AbteilungID = Abteilung.AbteilungID

UNION ALL

SELECT Angestellter.Nachname, Angestellter.AbteilungID, cast(NULL as varchar(20))
FROM Angestellter
WHERE NOT EXISTS (
    SELECT * FROM Abteilung
             WHERE Angestellter.AbteilungID = Abteilung.AbteilungID)

SELF JOIN

Ein SELF JOIN ist ein Join einer Tabelle auf sich selbst.[8]

Beispiel:

Im Falle zweier separater Tabellen für die Angestellten und einer Abfrage nach dem gleichen Land beider Tabellen, könnte eine gewöhnliche Join-Operation verwendet werden um die Antwort-Tabelle zu finden. Sehr oft finden sich jedoch alle Informationen innerhalb einer einzigen großen Tabelle..[9]

Die folgende Angestellter-Tabelle sei gegeben:

Tabelle: Angestellter
AngestellterID Nachname Land AbteilungID
123 Müller Australien 31
124 Schmidt Australien 33
145 Schneider Australien 33
201 Fischer Amerika 34
305 Weber Deutschland 34
306 Meyer Deutschland NULL

Eine mögliche Abfrage wäre:

SELECT F.AngestellterID, F.Nachname, S.AngestellterID, S.Nachname, F.Land
FROM Angestellter F <code>INNER JOIN</code> Angestellter S ON F.Land = S.Land
WHERE F.AngestellterID < S.AngestellterID
ORDER BY F.AngestellterID, S.AngestellterID;

Dies würde folgende Tabelle als Resultat ergeben:

Tabelle: Angestellter nach SELF JOIN mit Land
AngestellterID Nachname AngestellterID Nachname Land
123 Müller 124 Schmidt Australien
123 Müller 145 Schneider Australien
124 Schmidt 145 Schneider Australien
305 Weber 306 Meyer Deutschland

Zu diesem Beispiel:

  • F und S sind Aliase für die erste und zweite Kopie der Angestellter-Tabelle.
  • Die Bedingung F.Land = S.Land schließt die Paarbildung von Angestellten verschiedener Länder aus. Die obige Fragestellung suchte nach Angestellten im gleichen Land.
  • Die Bedingung F.AngestellterID < S.AngestellterID schließt die Paarbildung derer AngestellterIDs der ersten Angestellter-Tabelle aus die größer oder gleich der AngestellterID der zweiten Tabelle sind. In anderen Worten: die Folge dieser Bedingung ist das Auschließen duplizierter Paarbildungen und Selbst-Paarbildungen. Ohne sie würde die folgende weniger nützliche Tabelle erzeugt werden (nur der Ausschnitt des Results mit Deutschland ist gezeigt):
AngestellterID Nachname AngestellterID Nachname Land
305 Weber 305 Weber Deutschland
305 Weber 306 Meyer Deutschland
306 Meyer 305 Weber Deutschland
306 Meyer 306 Meyer Deutschland

Lediglich eine der beiden mittleren Paarbildungen sind nötig um der Fragestellung zu genügen: die oberste und unterste sind für dieses Beispiel nicht von Interesse.

Einbindung

Much work in database-systems has aimed at efficient implementation of joins, because relational systems commonly call for joins, yet face difficulties in optimising their efficient execution. The problem arises because INNER JOINs operate both kommutativ and assoziativ. In practice, this means that the user merely supplies the list of tables for joining and the join conditions to use, and the database system has the task of determining the most efficient way to perform the operation. A Abfrageoptimierer determines how to execute a query containing joins. A query optimizer has two basic freedoms:

  1. Join order: Because it joins functions commutatively and associatively, the order in which the system joins tables does not change the final result set of the query. However, join-order could have an enormous impact on the cost of the join operation, so choosing the best join order becomes very important.
  2. Join method: Given two tables and a join condition, multiple Algorithmen can produce the result set of the join. Which algorithm runs most efficiently depends on the sizes of the input tables, the number of rows from each table that match the join condition, and the operations required by the rest of the query.

Many join-algorithms treat their inputs differently. One can refer to the inputs to a join as the "outer" and "inner" join operands, or "LEFT" and "RIGHT", respectively. In the case of nested loops, for example, the database system will scan the entire inner relation for each row of the outer relation.

One can classify query-plans involving joins as follows:[10]

left-deep
using a base table (rather than another join) as the inner operand of each join in the plan
right-deep
using a base table as the outer operand of each join in the plan
bushy
neither left-deep nor right-deep; both inputs to a join may themselves result from joins

These names derive from the appearance of the Auswertungsplan if drawn as a Baum, with the OUTER JOIN relation on the LEFT and the inner relation on the RIGHT (as convention dictates).

Join-Algorithmen

Die drei fundamentalen Algorithmen für Join-Operation lauten: Nested Loop-Join, Sort-Merge Join und Hash-Join

Join-Indizes

Join indexes are Datenbankindizes that facilitate the processing of join queries in Data-Warehouses: they are currently (2012) available in implementations by Oracle[11] and Teradata.[12]

In the Teradata implementation, specified columns, aggregate functions on columns, or components of date columns from one or more tables are specified using a syntax similar to the definition of a View : up to 64 columns/column expressions can be specified in a single join index. Optionally, a column that defines the Primärschlüssel of the composite data may also be specified: on parallel hardware, the column values are used to partition the index's contents across multiple disks. When the source tables are updated interactively by users, the contents of the join index are automatically updated. Any query whose Where-Zusatz specifies any combination of columns or column expressions that are an exact subset of those defined in a join index (a so-called "covering query") will cause the join index, rather than the original tables and their indexes, to be consulted during query execution.

The Oracle implementation limits itself to using Bitmap-Indizes. A bitmap join index is used for low-cardinality columns (i.e., columns containing fewer than 300 distinct values, according to the Oracle documentation): it combines low-cardinality columns from multiple related tables. The example Oracle uses is that of an inventory system, where different suppliers provide different parts. The schema has three linked tables: two "master tables", Part and Supplier, and a "detail table", Inventory. The last is a many-to-many table linking Supplier to Part, and contains the most rows. Every part has a Part Type, and every supplier is based in the USA, and has a State column. There are not more than 60 states+territories in the USA, and not more than 300 Part Types. The bitmap join index is defined using a standard three-table join on the three tables above, and specifying the Part_Type and Supplier_State columns for the index. However, it is defined on the Inventory table, even though the columns Part_Type and Supplier_State are "borrowed" from Supplier and Part respectively.

As for Teradata, an Oracle bitmap join index is only utilized to answer a query when the query's Where-Zusatz specifies columns limited to those that are included in the join index.

STRAIGHT_JOIN

In manchen Datenbank-Systemen kann der Benutzer das Lesen der Tabellen eines Joins in einer bestimmten Reihenfolge erzwingen. Dies ist besonders hilfreich, wenn der Join-Optimierer die Tabellen in einer ineffizienten Reihenfolge abarbeitet. In MySQL beispielsweise werden mit dem Befehl STRAIGHT_JOIN die Tabellen in exakt der gleichen Reihenfolge gelesen, wie sie in der Abfrage aufgelistet wurden.[13]

Siehe auch

Weiterführende Literatur

  • Phillip J Pratt: A Guide To SQL, Seventh Edition. Thomson Course Technology, 2005, ISBN 978-0-619-21674-0.
  • Nilesh Shah: Database Systems Using Oracle – A Simplified Guide to SQL and PL/SQL Second Edition. International Auflage. Pearson Education International, 2005, ISBN 0-13-191180-5 ( [2002]).
  • Clement T. Yu, Weiyi Meng: Principles of Database Query Processing for Advanced Applications. Morgan Kaufmann, 1998, ISBN 978-1-55860-434-6 (google.com [abgerufen am 3. März 2009]).

Einzelnachweise

Kategorie:SQL

  1. SQL CROSS JOIN
  2. Greg Robidoux, "Avoid SQL Server functions in the WHERE clause for Performance", MSSQL Tips, 5/3/2007
  3. Patrick Wolf, "Inside Oracle APEX "Caution when using PL/SQL functions in a SQL statement", 11/30/2006
  4. Gregory A. Larsen, "T-SQL Best Practices - Don't Use Scalar Value Functions in Column List or WHERE Clauses", 10/29/2009,
  5. Simplifying Joins with the USING Keyword
  6. Ask Tom "Oracle support of ANSI joins." INNER JOINs/#comment-2837 Back to basics: INNER JOINs » Eddie Awad's Blog
  7. Oracle LEFT OUTER JOIN
  8. Shah, Nilesh (2005) [2002], Database Systems Using Oracle – A Simplified Guide to SQL and PL/SQL Second Edition (International ed.), Pearson Education International,S. 165
  9. Entnommen aus Pratt, Phillip J (2005), A Guide To SQL, Seventh Edition, Thomson Course Technology,S. 115– 116
  10. Yu, Clement T.; Meng, Weiyi (1998),| Principles of Database Query Processing for Advanced Applications S.213
  11. Oracle Bitmap Join Index. URL: http://www.dba-oracle.com/art_builder_bitmap_join_idx.htm
  12. Teradata Join Indexes. Archived copy. Archiviert vom Original am 16. Dezember 2012; abgerufen am 14. Juni 2012.
  13. 13.2.9.2 JOIN Syntax. In: MySQL 5.7 Reference Manual. Oracle Corporation, abgerufen am 3. Dezember 2015.