it-swarm.com.de

SQL JOIN und verschiedene Arten von JOINs

Was ist ein SQL JOIN und welche unterschiedlichen Typen gibt es?

232
M-D

Was ist SQL JOIN?

SQL JOIN ist eine Methode zum Abrufen von Daten aus zwei oder mehr Datenbanktabellen.

Was sind die verschiedenen SQL JOINs?

Es gibt insgesamt fünf JOINs. Sie sind :

  1. JOIN or INNER JOIN
  2. OUTER JOIN

     2.1 LEFT OUTER JOIN or LEFT JOIN
     2.2 RIGHT OUTER JOIN or RIGHT JOIN
     2.3 FULL OUTER JOIN or FULL JOIN

  3. NATURAL JOIN
  4. CROSS JOIN
  5. SELF JOIN

1. JOIN oder INNER JOIN:

In dieser Art von JOIN erhalten wir alle Datensätze, die der Bedingung in beiden Tabellen entsprechen, und Datensätze in beiden Tabellen, die nicht übereinstimmen, werden nicht gemeldet.

Mit anderen Worten, INNER JOIN basiert auf der einzigen Tatsache, dass: NUR die übereinstimmenden Einträge in BEIDEN Tabellen aufgeführt sein SOLLTEN.

Beachten Sie, dass ein JOIN ohne andere JOIN Schlüsselwörter (wie INNER, OUTER, LEFT usw.) ein INNER JOIN ist. Mit anderen Worten, JOIN ist ein syntaktischer Zucker für INNER JOIN (siehe: nterschied zwischen JOIN und INNER JOIN ).

2. OUTER JOIN:

OUTER JOIN wird abgerufen

Entweder die übereinstimmenden Zeilen aus einer Tabelle und alle Zeilen in der anderen Tabelle oder alle Zeilen in allen Tabellen (es spielt keine Rolle, ob eine Übereinstimmung vorliegt oder nicht).

Es gibt drei Arten von Outer Join:

2.1 LEFT OUTER JOIN oder LEFT JOIN

Dieser Join gibt alle Zeilen aus der linken Tabelle in Verbindung mit den übereinstimmenden Zeilen aus der rechten Tabelle zurück. Wenn in der rechten Tabelle keine übereinstimmenden Spalten vorhanden sind, werden NULL -Werte zurückgegeben.

2.2 RIGHT OUTER JOIN oder RIGHT JOIN

Dieses JOIN gibt alle Zeilen aus der rechten Tabelle in Verbindung mit den übereinstimmenden Zeilen aus der linken Tabelle zurück. Wenn in der linken Tabelle keine übereinstimmenden Spalten vorhanden sind, werden NULL -Werte zurückgegeben.

2.3 FULL OUTER JOIN oder FULL JOIN

Dieses JOIN kombiniert LEFT OUTER JOIN und RIGHT OUTER JOIN. Sie gibt Zeilen aus beiden Tabellen zurück, wenn die Bedingungen erfüllt sind, und gibt den Wert NULL zurück, wenn keine Übereinstimmung vorliegt.

Mit anderen Worten, OUTER JOIN basiert auf der Tatsache, dass: NUR die übereinstimmenden Einträge in EINER der Tabellen (RECHTS oder LINKS) oder BEIDEN der Tabellen (VOLL) aufgeführt sein SOLLTEN.

Note that `OUTER JOIN` is a loosened form of `INNER JOIN`.

3. NATÜRLICHE VERBINDUNG:

Es basiert auf den beiden Bedingungen:

  1. das JOIN wird für alle gleichnamigen Spalten erstellt, um die Gleichheit zu gewährleisten.
  2. Entfernt doppelte Spalten aus dem Ergebnis.

Dies scheint eher theoretischer Natur zu sein, weshalb sich (wahrscheinlich) die meisten DBMS nicht einmal darum kümmern, dies zu unterstützen.

4. CROSS JOIN:

Es ist das kartesische Produkt der beiden beteiligten Tabellen. Das Ergebnis eines CROSS JOIN ist in den meisten Situationen nicht sinnvoll. Darüber hinaus brauchen wir das überhaupt nicht (oder, um genau zu sein, am wenigsten).

5. SELBSTVERBINDUNG:

Es ist keine andere Form von JOIN, sondern eine JOIN (INNER, OUTER usw.) einer Tabelle für sich.

JOINs basierend auf Operatoren

Abhängig vom Operator, der für eine JOIN -Klausel verwendet wird, kann es zwei Arten von JOIN geben. Sie sind

  1. Equi JOIN
  2. Theta JOIN

1. Equi JOIN:

Für welchen JOIN -Typ (INNER, OUTER usw.) wir NUR den Gleichheitsoperator (=) verwenden, dann sagen wir, dass der JOIN ein EQUI JOIN ist.

2. Theta JOIN:

Dies ist dasselbe wie EQUI JOIN, erlaubt jedoch alle anderen Operatoren wie>, <,> = usw.

Viele betrachten sowohl EQUI JOIN als auch Theta JOIN ähnlich INNER, OUTER etc JOINs. Aber ich bin der festen Überzeugung, dass dies ein Fehler ist und die Ideen vage werden lässt. Da INNER JOIN, OUTER JOIN usw. alle mit den Tabellen und ihren Daten verbunden sind, sind EQUI JOIN und THETA JOIN nur mit den Operatoren verbunden, die wir in den ersteren verwenden.

Wiederum gibt es viele, die NATURAL JOIN als eine Art "eigentümlichen" EQUI JOIN betrachten. In der Tat ist es wahr, wegen der ersten Bedingung, die ich für NATURAL JOIN erwähnte. Wir müssen dies jedoch nicht nur auf NATURAL JOINs beschränken. INNER JOINs, OUTER JOINs usw. können auch ein EQUI JOIN sein.

239
M-D

Eine Illustration von W3schools :


INNER JOIN - Only records which match the condition in both tables


LEFT JOIN - All records from table 1 in conjunction with records which match the condition in table 2


RIGHT JOIN - All records from table 2 in conjunction with records from table 1 which match the condition


FULL OUTER JOIN - Combination of both Left and Right Outer joins matching ON clause but preserving both tables


321
Anup

Definition:


Mit JOINS können Sie die Daten abfragen, die gleichzeitig aus mehreren Tabellen kombiniert wurden.

Arten von JOINS:


In Bezug auf RDBMS gibt es 5 Arten von Joins:

  • Equi-Join: Kombiniert gemeinsame Datensätze aus zwei Tabellen basierend auf der Gleichheitsbedingung. Technisch gesehen wird ein Join mit dem Gleichheitsoperator (=) erstellt, um die Werte des Primärschlüssels einer Tabelle und die Werte des Fremdschlüssels einer anderen Tabelle zu vergleichen. Die Ergebnismenge enthält daher gemeinsame (übereinstimmende) Datensätze aus beiden Tabellen. Zur Implementierung siehe INNER-JOIN.

  • Natural-Join: Es handelt sich um eine erweiterte Version von Equi-Join, bei der bei der SELECT-Operation doppelte Spalten weggelassen werden. Zur Implementierung siehe INNER-JOIN

  • Non-Equi-Join: Dies ist die Umkehrung von Equi-Join, wenn eine andere Verknüpfungsbedingung als der Gleichheitsoperator (=) verwendet wird, z. B.! =, <= ,> =,>, <oder ZWISCHEN usw. Zur Implementierung siehe INNER-JOIN.

  • Self-Join: : Ein benutzerdefiniertes Join-Verhalten, bei dem eine Tabelle mit sich selbst kombiniert wird. Dies wird normalerweise zum Abfragen von selbstreferenzierenden Tabellen (oder von Entitäten mit unären Beziehungen) benötigt. Zur Implementierung siehe INNER-JOINs.

  • Kartesisches Produkt: Kreuzt alle Datensätze beider Tabellen ohne Bedingung. Technisch gibt es die Ergebnismenge einer Abfrage ohne WHERE-Klausel zurück.

In Bezug auf SQL gibt es drei Arten von Joins und alle RDBMS-Joins können mit diesen Arten von Joins erstellt werden.

  1. INNER-JOIN: Führt übereinstimmende Zeilen aus zwei Tabellen zusammen (oder kombiniert sie). Der Abgleich erfolgt anhand gemeinsamer Tabellenspalten und ihrer Vergleichsoperation. Wenn Gleichheitsbedingung dann: EQUI-JOIN durchgeführt, sonst Non-EQUI-Join.

  2. OUTER-JOIN: Führt übereinstimmende Zeilen aus zwei Tabellen und nicht übereinstimmende Zeilen mit NULL-Werten zusammen (oder kombiniert sie). Es kann jedoch eine angepasste Auswahl von nicht übereinstimmenden Zeilen erfolgen, z. B. Auswählen einer nicht übereinstimmenden Zeile aus der ersten Tabelle oder der zweiten Tabelle nach Untertypen: LINKS-AUSSEN-VERBINDUNG und RECHTS-AUSSEN-VERBINDUNG.

    2.1. LEFT Outer JOIN (a.k.a, LEFT-JOIN): Gibt nur übereinstimmende Zeilen aus zwei Tabellen zurück, die nicht mit der LEFT-Tabelle übereinstimmen (d. H. Erste Tabelle).

    2.2. RIGHT Outer JOIN (a.k.a., RIGHT-JOIN): Gibt nur übereinstimmende Zeilen aus zwei Tabellen zurück, die nicht mit der Tabelle RIGHT übereinstimmen.

    2.3. FULL OUTER JOIN (a.k.a OUTER JOIN): Gibt Übereinstimmungen und Übereinstimmungen beider Tabellen zurück.

  3. CROSS-JOIN: Dieser Join führt keine Zusammenführung/Kombination durch, sondern führt ein kartesisches Produkt aus.

enter image description here Hinweis: Self-JOIN kann je nach Anforderung entweder über INNER-JOIN, OUTER-JOIN oder CROSS-JOIN ausgeführt werden, die Tabelle muss sich jedoch selbst verbinden.

Weitere Informationen:

Beispiele:

1.1: INNER-JOIN: Equi-Join-Implementierung

SELECT  *
FROM Table1 A 
 INNER JOIN Table2 B ON A.<Primary-Key> =B.<Foreign-Key>;

1.2: INNER-JOIN: Natural-JOIN-Implementierung

Select A.*, B.Col1, B.Col2          --But no B.ForeignKeyColumn in Select
 FROM Table1 A
 INNER JOIN Table2 B On A.Pk = B.Fk;

1.3: INNER-JOIN mit NON-Equi-Join-Implementierung

Select *
 FROM Table1 A INNER JOIN Table2 B On A.Pk <= B.Fk;

1.4: INNER-JOIN mit SELF-JOIN

Select *
 FROM Table1 A1 INNER JOIN Table1 A2 On A1.Pk = A2.Fk;

2.1: OUTER JOIN (vollständiger Outer Join)

Select *
 FROM Table1 A FULL OUTER JOIN Table2 B On A.Pk = B.Fk;

2.2: LEFT JOIN

Select *
 FROM Table1 A LEFT OUTER JOIN Table2 B On A.Pk = B.Fk;

2.3: RIGHT JOIN

Select *
 FROM Table1 A RIGHT OUTER JOIN Table2 B On A.Pk = B.Fk;

3.1: CROSS JOIN

Select *
 FROM TableA CROSS JOIN TableB;

3.2: CROSS JOIN-Self JOIN

Select *
 FROM Table1 A1 CROSS JOIN Table1 A2;

//ODER//

Select *
 FROM Table1 A1,Table1 A2;

Interessanterweise leiden die meisten anderen Antworten unter diesen beiden Problemen:

Ich habe kürzlich einen Artikel zum Thema geschrieben: Eine wahrscheinlich unvollständige, umfassende Anleitung zu den vielen verschiedenen Möglichkeiten, Tabellen in SQL zu verbinden, die ich hier zusammenfassen werde.

In erster Linie: JOINs sind kartesische Produkte

Deshalb erklären Venn-Diagramme sie so ungenau, weil ein JOIN ein kartesisches Produkt zwischen den beiden verknüpften Tabellen erzeugt. Wikipedia illustriert es gut:

enter image description here

Die SQL-Syntax für kartesische Produkte lautet CROSS JOIN. Zum Beispiel:

SELECT *

-- This just generates all the days in January 2017
FROM generate_series(
  '2017-01-01'::TIMESTAMP,
  '2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',
  INTERVAL '1 day'
) AS days(day)

-- Here, we're combining all days with all departments
CROSS JOIN departments

Welche kombiniert alle Zeilen aus einer Tabelle mit allen Zeilen aus der anderen Tabelle:

Quelle:

+--------+   +------------+
| day    |   | department |
+--------+   +------------+
| Jan 01 |   | Dept 1     |
| Jan 02 |   | Dept 2     |
| ...    |   | Dept 3     |
| Jan 30 |   +------------+
| Jan 31 |
+--------+

Ergebnis:

+--------+------------+
| day    | department |
+--------+------------+
| Jan 01 | Dept 1     |
| Jan 01 | Dept 2     |
| Jan 01 | Dept 3     |
| Jan 02 | Dept 1     |
| Jan 02 | Dept 2     |
| Jan 02 | Dept 3     |
| ...    | ...        |
| Jan 31 | Dept 1     |
| Jan 31 | Dept 2     |
| Jan 31 | Dept 3     |
+--------+------------+

Wenn wir nur eine durch Kommas getrennte Liste von Tabellen schreiben, erhalten wir dasselbe:

-- CROSS JOINing two tables:
SELECT * FROM table1, table2

INNER JOIN (Theta-JOIN)

Ein INNER JOIN ist nur ein gefilterter CROSS JOIN, wobei das Filterprädikat in der relationalen Algebra Theta heißt.

Zum Beispiel:

SELECT *

-- Same as before
FROM generate_series(
  '2017-01-01'::TIMESTAMP,
  '2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',
  INTERVAL '1 day'
) AS days(day)

-- Now, exclude all days/departments combinations for
-- days before the department was created
JOIN departments AS d ON day >= d.created_at

Beachten Sie, dass das Schlüsselwort INNER optional ist (außer in MS Access).

( siehe Artikel für Ergebnisbeispiele )

EQUI JOIN

Eine besondere Art von Theta-JOIN ist equi JOIN, die wir am häufigsten verwenden. Das Prädikat verknüpft den Primärschlüssel einer Tabelle mit dem Fremdschlüssel einer anderen Tabelle. Wenn wir die Sakila-Datenbank zur Veranschaulichung verwenden, können wir schreiben:

SELECT *
FROM actor AS a
JOIN film_actor AS fa ON a.actor_id = fa.actor_id
JOIN film AS f ON f.film_id = fa.film_id

Dies verbindet alle Schauspieler mit ihren Filmen.

Oder auch in einigen Datenbanken:

SELECT *
FROM actor
JOIN film_actor USING (actor_id)
JOIN film USING (film_id)

Die Syntax USING() ermöglicht die Angabe einer Spalte, die auf beiden Seiten der Tabellen einer JOIN-Operation vorhanden sein muss, und erstellt für diese beiden Spalten ein Gleichheitsprädikat.

NATÜRLICHE VERBINDUNG

Andere Antworten haben diesen "JOIN-Typ" separat aufgelistet, aber das macht keinen Sinn. Es ist nur eine Syntaxzuckerform für equi JOIN, was ein Sonderfall von Theta-JOIN oder INNER JOIN ist. NATURAL JOIN sammelt einfach alle Spalten, die für beide Tabellen gelten, die verbunden werden, und verknüpft USING() diese Spalten. Was wegen versehentlicher Übereinstimmungen (wie LAST_UPDATE Spalten in der Sakila-Datenbank ) kaum nützlich ist.

Hier ist die Syntax:

SELECT *
FROM actor
NATURAL JOIN film_actor
NATURAL JOIN film

OUTER JOIN

Jetzt unterscheidet sich OUTER JOIN ein wenig von INNER JOIN, da UNION aus mehreren kartesischen Produkten erstellt wird. Wir können schreiben:

-- Convenient syntax:
SELECT *
FROM a LEFT JOIN b ON <predicate>

-- Cumbersome, equivalent syntax:
SELECT a.*, b.*
FROM a JOIN b ON <predicate>
UNION ALL
SELECT a.*, NULL, NULL, ..., NULL
FROM a
WHERE NOT EXISTS (
  SELECT * FROM b WHERE <predicate>
)

Niemand möchte letzteres schreiben, also schreiben wir OUTER JOIN (was normalerweise besser durch Datenbanken optimiert wird).

Wie bei INNER ist das Schlüsselwort OUTER hier optional.

OUTER JOIN gibt es in drei Varianten:

  • LEFT [ OUTER ] JOIN: Die linke Tabelle des Ausdrucks JOIN wird wie oben gezeigt zur Vereinigung hinzugefügt.
  • RIGHT [ OUTER ] JOIN: Die rechte Tabelle des Ausdrucks JOIN wird wie oben gezeigt zur Vereinigung hinzugefügt.
  • FULL [ OUTER ] JOIN: Beide Tabellen des Ausdrucks JOIN werden wie oben gezeigt zur Union hinzugefügt.

All dies kann mit dem Schlüsselwort USING() oder mit NATURAL kombiniert werden. ( Ich hatte tatsächlich einen realen Anwendungsfall für einen NATURAL FULL JOIN in letzter Zeit )

Alternative Syntaxen

Es gibt einige alte, veraltete Syntax in Oracle und SQL Server, die OUTER JOIN bereits unterstützten, bevor der SQL-Standard eine Syntax dafür hatte:

-- Oracle
SELECT *
FROM actor a, film_actor fa, film f
WHERE a.actor_id = fa.actor_id(+)
AND fa.film_id = f.film_id(+)

-- SQL Server
SELECT *
FROM actor a, film_actor fa, film f
WHERE a.actor_id *= fa.actor_id
AND fa.film_id *= f.film_id

Verwenden Sie diese Syntax jedoch nicht. Ich liste dies hier nur auf, damit Sie es aus alten Blog-Posts/Legacy-Code erkennen können.

Partitioniert OUTER JOIN

Wenige Leute wissen das, aber der SQL-Standard spezifiziert partitioned OUTER JOIN (und Oracle implementiert es). Sie können solche Dinge schreiben:

WITH

  -- Using CONNECT BY to generate all dates in January
  days(day) AS (
    SELECT DATE '2017-01-01' + LEVEL - 1
    FROM dual
    CONNECT BY LEVEL <= 31
  ),

  -- Our departments
  departments(department, created_at) AS (
    SELECT 'Dept 1', DATE '2017-01-10' FROM dual UNION ALL
    SELECT 'Dept 2', DATE '2017-01-11' FROM dual UNION ALL
    SELECT 'Dept 3', DATE '2017-01-12' FROM dual UNION ALL
    SELECT 'Dept 4', DATE '2017-04-01' FROM dual UNION ALL
    SELECT 'Dept 5', DATE '2017-04-02' FROM dual
  )
SELECT *
FROM days 
LEFT JOIN departments 
  PARTITION BY (department) -- This is where the magic happens
  ON day >= created_at

Teile des Ergebnisses:

+--------+------------+------------+
| day    | department | created_at |
+--------+------------+------------+
| Jan 01 | Dept 1     |            | -- Didn't match, but still get row
| Jan 02 | Dept 1     |            | -- Didn't match, but still get row
| ...    | Dept 1     |            | -- Didn't match, but still get row
| Jan 09 | Dept 1     |            | -- Didn't match, but still get row
| Jan 10 | Dept 1     | Jan 10     | -- Matches, so get join result
| Jan 11 | Dept 1     | Jan 10     | -- Matches, so get join result
| Jan 12 | Dept 1     | Jan 10     | -- Matches, so get join result
| ...    | Dept 1     | Jan 10     | -- Matches, so get join result
| Jan 31 | Dept 1     | Jan 10     | -- Matches, so get join result

Der Punkt hier ist, dass alle Zeilen von der partitionierten Seite des Joins im Ergebnis angezeigt werden, unabhängig davon, ob JOIN mit etwas auf der "anderen Seite des JOINS" übereinstimmt. Kurz gesagt: Damit füllen Sie Berichte mit wenigen Daten. Sehr hilfreich!

SEMI JOIN

Ernsthaft? Keine andere Antwort hat das? Natürlich nicht , da es in SQL leider keine native Syntax hat (genau wie ANTI JOIN unten). Wir können jedoch IN() und EXISTS() verwenden, z. um alle Schauspieler zu finden, die in Filmen mitgespielt haben:

SELECT *
FROM actor a
WHERE EXISTS (
  SELECT * FROM film_actor fa
  WHERE a.actor_id = fa.actor_id
)

Das Prädikat WHERE a.actor_id = fa.actor_id fungiert als Semi-Join-Prädikat. Wenn Sie es nicht glauben, überprüfen Sie die Ausführungspläne, z. in Oracle. Sie werden sehen, dass die Datenbank eine SEMI JOIN-Operation ausführt, nicht das Prädikat EXISTS().

enter image description here

ANTI JOIN

Dies ist genau das Gegenteil von SEMI JOIN ( Achten Sie darauf, NOT IN nicht zu verwenden, obwohl , da es eine wichtige Einschränkung hat)

Hier sind alle Schauspieler ohne Filme:

SELECT *
FROM actor a
WHERE NOT EXISTS (
  SELECT * FROM film_actor fa
  WHERE a.actor_id = fa.actor_id
)

Einige Leute (insbesondere MySQL-Leute) schreiben ANTI JOIN auch so:

SELECT *
FROM actor a
LEFT JOIN film_actor fa
USING (actor_id)
WHERE film_id IS NULL

Ich denke, der historische Grund ist die Leistung.

LATERAL JOIN

OMG, das ist zu cool. Ich bin der einzige, der es erwähnt? Hier ist eine coole Frage:

SELECT a.first_name, a.last_name, f.*
FROM actor AS a
LEFT OUTER JOIN LATERAL (
  SELECT f.title, SUM(amount) AS revenue
  FROM film AS f
  JOIN film_actor AS fa USING (film_id)
  JOIN inventory AS i USING (film_id)
  JOIN rental AS r USING (inventory_id)
  JOIN payment AS p USING (rental_id)
  WHERE fa.actor_id = a.actor_id -- JOIN predicate with the outer query!
  GROUP BY f.film_id
  ORDER BY revenue DESC
  LIMIT 5
) AS f
ON true

Es werden die TOP 5 Einnahmen produzierenden Filme pro Darsteller ermittelt. Jedes Mal, wenn Sie eine TOP-N-per-Something-Abfrage benötigen, ist LATERAL JOIN Ihr Freund. Wenn Sie eine SQL Server-Person sind, kennen Sie diesen JOIN Typ unter dem Namen APPLY

SELECT a.first_name, a.last_name, f.*
FROM actor AS a
OUTER APPLY (
  SELECT f.title, SUM(amount) AS revenue
  FROM film AS f
  JOIN film_actor AS fa ON f.film_id = fa.film_id
  JOIN inventory AS i ON f.film_id = i.film_id
  JOIN rental AS r ON i.inventory_id = r.inventory_id
  JOIN payment AS p ON r.rental_id = p.rental_id
  WHERE fa.actor_id = a.actor_id -- JOIN predicate with the outer query!
  GROUP BY f.film_id
  ORDER BY revenue DESC
  LIMIT 5
) AS f

OK, vielleicht ist das Schummeln, weil ein LATERAL JOIN oder APPLY Ausdruck wirklich eine "korrelierte Unterabfrage" ist, die mehrere Zeilen erzeugt. Wenn wir aber "korrelierte Unterabfragen" zulassen, können wir auch über ... sprechen.

MULTISET

Dies wird meines Wissens nur von Oracle und Informix wirklich implementiert, kann jedoch in PostgreSQL mithilfe von Arrays und/oder XML und in SQL Server mithilfe von XML emuliert werden.

MULTISET erstellt eine korrelierte Unterabfrage und verschachtelt die resultierende Menge von Zeilen in der äußeren Abfrage. Die folgende Abfrage wählt alle Schauspieler aus und sammelt für jeden Schauspieler ihre Filme in einer verschachtelten Sammlung:

SELECT a.*, MULTISET (
  SELECT f.*
  FROM film AS f
  JOIN film_actor AS fa USING (film_id)
  WHERE a.actor_id = fa.actor_id
) AS films
FROM actor

Wie Sie gesehen haben, gibt es mehr Arten von JOIN als nur die "langweiligen" INNER, OUTER und CROSS JOIN, die normalerweise erwähnt werden. Weitere Details in meinem Artikel . Und bitte verwenden Sie keine Venn-Diagramme mehr, um sie zu veranschaulichen.

37
Lukas Eder

Ich habe eine Illustration erstellt, die meiner Meinung nach besser als Worte erklärt: SQL Join table of explanation

9
Gisway