Einführung
Das Aufteilen verwandter Daten in separate Tabellen kann im Hinblick auf Konsistenz, Flexibilität und bestimmte Arten von Leistung vorteilhaft sein. Sie benötigen jedoch immer noch eine vernünftige Möglichkeit, Datensätze wieder zu integrieren, wenn sich die relevanten Informationen über mehrere Tabellen erstrecken.
In relationalen Datenbanken Joins bieten eine Möglichkeit, die Datensätze in zwei oder mehr Tabellen basierend auf gemeinsamen Feldwerten zu kombinieren. Unterschiedliche Arten von Joins können unterschiedliche Ergebnisse erzielen, je nachdem, wie nicht übereinstimmende Zeilen behandelt werden sollen. In diesem Leitfaden besprechen wir die verschiedenen Arten von Verknüpfungen, die PostgreSQL bietet, und wie Sie sie verwenden können, um Tabellendaten aus mehreren Quellen zu kombinieren.
Was sind Joins?
Kurz gesagt, tritt bei sind eine Möglichkeit, Daten aus mehreren Tabellen anzuzeigen. Sie tun dies, indem sie Datensätze aus verschiedenen Quellen basierend auf übereinstimmenden Werten in bestimmten Spalten zusammenfügen. Jede resultierende Zeile besteht aus einem Datensatz aus der ersten Tabelle kombiniert mit einer Zeile aus der zweiten Tabelle, basierend darauf, dass eine oder mehrere Spalten in jeder Tabelle denselben Wert haben.
Die grundlegende Syntax eines Joins sieht folgendermaßen aus:
SELECT *FROM <first_table><join_type> <second_table> <join_condition>;
Bei einem Join wird jede resultierende Zeile erstellt, indem alle Spalten der ersten Tabelle gefolgt von allen Spalten der zweiten Tabelle eingeschlossen werden. Die SELECT
Teil der Abfrage kann verwendet werden, um genau die Spalten anzugeben, die Sie anzeigen möchten.
Aus den Originaltabellen können mehrere Zeilen erstellt werden, wenn die Werte in den zum Vergleich verwendeten Spalten nicht eindeutig sind. Stellen Sie sich beispielsweise vor, Sie haben eine Spalte, die mit der ersten Tabelle verglichen wird, die zwei Datensätze mit dem Wert „rot“ enthält. Damit abgeglichen ist eine Spalte aus der zweiten Tabelle, die drei Zeilen mit diesem Wert enthält. Der Join erzeugt sechs verschiedene Zeilen für diesen Wert, die die verschiedenen Kombinationen darstellen, die erreicht werden können.
Der Join-Typ und die Join-Bedingungen bestimmen, wie jede angezeigte Zeile aufgebaut ist. Dies wirkt sich darauf aus, was mit den Zeilen aus jeder Tabelle passiert, die dies tun und nicht tun eine Übereinstimmung mit der Join-Bedingung haben.
Der Einfachheit halber gleichen viele Joins den Primärschlüssel in einer Tabelle mit einem zugehörigen Fremdschlüssel in der zweiten Tabelle ab. Obwohl Primär- und Fremdschlüssel nur vom Datenbanksystem verwendet werden, um Konsistenzgarantien aufrechtzuerhalten, macht ihre Beziehung sie oft zu einem guten Kandidaten für Join-Bedingungen.
Verschiedene Arten von Joins
Es stehen verschiedene Arten von Joins zur Verfügung, von denen jede möglicherweise unterschiedliche Ergebnisse liefert. Wenn Sie verstehen, wie jeder Typ aufgebaut ist, können Sie bestimmen, welcher für verschiedene Szenarien geeignet ist.
Innere Verbindung
Der Standard-Join wird als innerer Join bezeichnet . In PostgreSQL kann dies entweder mit INNER JOIN
angegeben werden oder einfach JOIN
.
Hier ist ein typisches Beispiel, das die Syntax eines inneren Joins demonstriert:
SELECT *FROM table_1[INNER] JOIN table_2 ON table_1.id = table_2.table_1_id;
Ein innerer Join ist der restriktivste Join-Typ, da er nur Zeilen anzeigt, die durch Kombinieren von Zeilen aus jeder Tabelle erstellt wurden. Alle Zeilen in den konstituierenden Tabellen, die kein übereinstimmendes Gegenstück in der anderen Tabelle hatten, werden aus den Ergebnissen entfernt. Wenn beispielsweise die erste Tabelle den Wert „blau“ in der Vergleichsspalte hat und die zweite Tabelle keinen Datensatz mit diesem Wert hat, wird diese Zeile aus der Ausgabe unterdrückt.
Wenn Sie die Ergebnisse als Venn-Diagramm der Komponententabellen darstellen, können Sie mit einem Inner Join den überlappenden Bereich der beiden Kreise darstellen. Es werden keine Werte angezeigt, die nur in einer der Tabellen vorhanden waren.
Linker Join
Ein Left Join ist ein Join, der alle in einem Inner Join gefundenen Datensätze sowie alle nicht übereinstimmenden anzeigt Zeilen aus der ersten Tabelle. In PostgreSQL kann dies als LEFT OUTER JOIN
angegeben werden oder einfach als LEFT JOIN
.
Die grundlegende Syntax einer Linksverknüpfung folgt diesem Muster:
SELECT *FROM table_1LEFT JOIN table_2 ON table_1.id = table_2.table_1_id;
Eine linke Verknüpfung wird erstellt, indem zuerst eine innere Verknüpfung ausgeführt wird, um Zeilen aus allen übereinstimmenden Datensätzen in beiden Tabellen zu erstellen. Danach werden auch die nicht abgeglichenen Datensätze aus der ersten Tabelle aufgenommen. Da jede Zeile in einem Join die Spalten beider Tabellen enthält, verwenden die nicht übereinstimmenden Spalten NULL
als Wert für alle Spalten in der zweiten Tabelle.
Wenn Sie die Ergebnisse als Venn-Diagramm der Komponententabellen darstellen, können Sie mit einem linken Join den gesamten linken Kreis darstellen. Die Teile des linken Kreises, die durch den Schnittpunkt zwischen den beiden Kreisen dargestellt werden, enthalten zusätzliche Daten, die durch die rechte Tabelle ergänzt werden.
Right Join
Ein Right Join ist ein Join, der alle in einem Inner Join gefundenen Datensätze sowie alle nicht übereinstimmenden anzeigt Zeilen aus der zweiten Tabelle. In PostgreSQL kann dies als RIGHT OUTER JOIN
angegeben werden oder einfach als RIGHT JOIN
.
Die grundlegende Syntax eines Right Joins folgt diesem Muster:
SELECT *FROM table_1RIGHT JOIN table_2 ON table_1.id = table_2.table_1_id;
Eine rechte Verknüpfung wird erstellt, indem zuerst eine innere Verknüpfung ausgeführt wird, um Zeilen aus allen übereinstimmenden Datensätzen in beiden Tabellen zu erstellen. Danach werden auch die nicht abgeglichenen Datensätze aus der zweiten Tabelle aufgenommen. Da jede Zeile in einem Join die Spalten beider Tabellen enthält, verwenden die nicht übereinstimmenden Spalten NULL
als Wert für alle Spalten in der ersten Tabelle.
Wenn Sie die Ergebnisse als Venn-Diagramm der Komponententabellen darstellen, können Sie mit einem Right Join den gesamten rechten Kreis darstellen. Die Teile des rechten Kreises, die durch den Schnittpunkt zwischen den beiden Kreisen dargestellt werden, enthalten zusätzliche Daten, die durch die linke Tabelle ergänzt werden.
Vollständiger Beitritt
Ein vollständiger Join ist ein Join, der alle Datensätze anzeigt, die in einem Inner Join gefunden wurden, plus alle nicht übereinstimmenden Zeilen aus beiden Komponententabellen. In PostgreSQL kann dies als FULL OUTER JOIN
angegeben werden oder nur als FULL JOIN
.
Die grundlegende Syntax eines vollständigen Joins folgt diesem Muster:
SELECT *FROM table_1FULL JOIN table_2 ON table_1.id = table_2.table_1_id;
Eine vollständige Verknüpfung wird erstellt, indem zuerst eine innere Verknüpfung ausgeführt wird, um Zeilen aus allen übereinstimmenden Datensätzen in beiden Tabellen zu erstellen. Danach werden auch die nicht abgeglichenen Datensätze aus beiden Tabellen aufgenommen. Da jede Zeile in einem Join die Spalten beider Tabellen enthält, verwenden die nicht übereinstimmenden Spalten NULL
als Wert für alle Spalten in der nicht übereinstimmenden anderen Tabelle.
Wenn Sie die Ergebnisse als Venn-Diagramm der Komponententabellen darstellen, können Sie mit einem vollständigen Join beide Komponentenkreise vollständig darstellen. Der Schnittpunkt der beiden Kreise wird Werte aufweisen, die von jeder der Komponententabellen geliefert werden. Die Teile der Kreise außerhalb des überlappenden Bereichs haben die Werte aus der Tabelle, zu der sie gehören, wobei NULL
verwendet wird um die in der anderen Tabelle gefundenen Spalten auszufüllen.
Cross-Join
Ein spezieller Join namens CROSS JOIN
ist ebenfalls verfügbar. Ein Cross Join verwendet keine Vergleiche, um zu bestimmen, ob die Zeilen in jeder Tabelle miteinander übereinstimmen. Stattdessen werden Ergebnisse konstruiert, indem einfach jede der Zeilen aus der ersten Tabelle zu jeder der Zeilen der zweiten Tabelle hinzugefügt wird.
Dies erzeugt ein kartesisches Produkt der Zeilen in zwei oder mehr Tabellen. Tatsächlich kombiniert dieser Join-Stil Zeilen aus jeder Tabelle bedingungslos. Wenn also jede Tabelle drei Zeilen hat, hätte die resultierende Tabelle neun Zeilen, die alle Spalten aus beiden Tabellen enthalten.
Zum Beispiel, wenn Sie eine Tabelle mit dem Namen t1
haben kombiniert mit einer Tabelle namens t2
, jeweils mit Zeilen r1
, r2
, und r3
, wäre das Ergebnis neun Zeilen kombiniert wie folgt:
t1.r1 + t2.r1t1.r1 + t2.r2t1.r1 + t2.r3t1.r2 + t2.r1t1.r2 + t2.r2t1.r2 + t2.r3t1.r3 + t2.r1t1.r3 + t2.r2t1.r3 + t2.r3
Selbstbeitritt
Ein Self-Join ist ein Join, der die Zeilen einer Tabelle mit sich selbst kombiniert. Es mag nicht sofort ersichtlich sein, wie dies nützlich sein könnte, aber es hat tatsächlich viele allgemeine Anwendungen.
Häufig beschreiben Tabellen Entitäten, die mehrere Rollen in Beziehung zueinander erfüllen können. Zum Beispiel, wenn Sie eine Tabelle mit people
haben , könnte jede Zeile möglicherweise eine mother
enthalten Spalte, die auf andere people
verweisen in der Tabelle. Eine Selbstverknüpfung würde es Ihnen ermöglichen, diese verschiedenen Zeilen zusammenzufügen, indem Sie eine zweite Instanz der Tabelle mit der ersten verknüpfen, in der diese Werte übereinstimmen.
Da Self-Joins zweimal auf dieselbe Tabelle verweisen, sind Tabellenaliasnamen erforderlich, um die Verweise eindeutig zu machen. Im obigen Beispiel könnten Sie beispielsweise den beiden Instanzen der people
beitreten Tabelle mit den Aliasen people AS children
und people AS mothers
. Auf diese Weise können Sie angeben, auf welche Instanz der Tabelle Sie sich beziehen, wenn Sie Join-Bedingungen definieren.
Hier ist ein weiteres Beispiel, diesmal für die Beziehungen zwischen Mitarbeitern und Managern:
SELECT *FROM people AS employeeJOIN people AS manager ON employee.manager_id = manager.id;
Beitrittsbedingungen
Beim Kombinieren von Tabellen bestimmt die Join-Bedingung, wie Zeilen abgeglichen werden, um die zusammengesetzten Ergebnisse zu bilden. Die grundlegende Prämisse besteht darin, die Spalten in jeder Tabelle zu definieren, die übereinstimmen müssen, damit der Join in dieser Zeile erfolgt.
Der ON
Klausel
Die üblichste Art, die Bedingungen für Tabellenverknüpfungen zu definieren, ist mit ON
Klausel. Das ON
-Klausel verwendet ein Gleichheitszeichen, um die genauen Spalten aus jeder Tabelle anzugeben, die verglichen werden, um zu bestimmen, wann ein Join erfolgen kann. PostgreSQL verwendet die bereitgestellten Spalten, um die Zeilen aus jeder Tabelle zusammenzufügen.
Das ON
-Klausel ist die ausführlichste, aber auch die flexibelste der verfügbaren Join-Bedingungen. Es ermöglicht Spezifität, unabhängig davon, wie standardisiert die Spaltennamen jeder kombinierten Tabelle sind.
Die grundlegende Syntax des ON
Klausel sieht so aus:
SELECT *FROM table1JOIN table2ON table1.id = table2.ident;
Hier die Zeilen aus table1
und table2
wird zusammengefügt, wenn die id
Spalte aus table1
entspricht dem ident
Spalte aus table2
. Da ein innerer Join verwendet wird, zeigen die Ergebnisse nur die Zeilen, die verbunden wurden. Da die Abfrage den Platzhalter *
verwendet Zeichen werden alle Spalten aus beiden Tabellen angezeigt.
Das bedeutet, dass sowohl die id
Spalte aus table1
und die ident
Spalte aus table2
angezeigt, obwohl sie aufgrund der Erfüllung der Join-Bedingung genau denselben Wert haben. Sie können diese Duplizierung vermeiden, indem Sie genau die Spalten aufrufen, die Sie im SELECT
anzeigen möchten Spaltenliste.
Der USING
Klausel
Der USING
-Klausel ist eine Abkürzung für die Angabe der Bedingungen eines ON
-Klausel, die verwendet werden kann, wenn die zu vergleichenden Spalten in beiden Tabellen denselben Namen haben. Der USING
-Klausel nimmt eine in Klammern eingeschlossene Liste der gemeinsam genutzten Spaltennamen, die verglichen werden sollen.
Die allgemeine Syntax von USING
-Klausel verwendet dieses Format:
SELECT *FROM table1JOIN table2USING (id, state);
Dieser Join kombiniert table1
mit table2
wenn zwei Spalten, die beide Tabellen teilen (id
und state
) haben jeweils übereinstimmende Werte.
Dieselbe Verknüpfung könnte mit ON
ausführlicher ausgedrückt werden so:
SELECT *FROM table1JOIN table2ON table1.id = table2.id AND table1.state = table2.state;
Während beide oben genannten Verknüpfungen dazu führen würden, dass dieselben Zeilen mit denselben vorhandenen Daten erstellt würden, würden sie etwas anders angezeigt. Während der ON
-Klausel enthält alle Spalten aus beiden Tabellen, den USING
-Klausel unterdrückt die doppelten Spalten. Anstelle von zwei getrennten id
Spalten und zwei separate state
Spalten (eine für jede Tabelle), würden die Ergebnisse nur eine von jeder der gemeinsam genutzten Spalten enthalten, gefolgt von allen anderen Spalten, die von table1
bereitgestellt werden und table2
.
Der NATURAL
Klausel
Das NATURAL
-Klausel ist eine weitere Abkürzung, die die Ausführlichkeit von USING
weiter reduzieren kann Klausel. Ein NATURAL
join gibt any nicht an Spalten abgeglichen werden. Stattdessen verbindet PostgreSQL die Tabellen automatisch basierend auf allen Spalten, die übereinstimmende Spalten in jeder Datenbank haben.
Die allgemeine Syntax des NATURAL
Join-Klausel sieht so aus:
SELECT *FROM table1NATURAL JOIN table2;
Angenommen, dass table1
und table2
beide haben Spalten namens id
, state
, und company
, wäre die obige Abfrage äquivalent zu dieser Abfrage mit ON
Klausel:
SELECT *FROM table1JOIN table2ON table1.id = table2.id AND table1.state = table2.state AND table1.company = table2.company;
Und diese Abfrage mit dem USING
Klausel:
SELECT *FROM table1JOIN table2USING (id, state, company);
Wie das USING
-Klausel, die NATURAL
-Klausel unterdrückt doppelte Spalten, sodass in den Ergebnissen nur eine einzige Instanz jeder der verbundenen Spalten vorhanden wäre.
Während die NATURAL
-Klausel die Ausführlichkeit Ihrer Abfragen verringern kann, ist bei ihrer Verwendung Vorsicht geboten. Da die zum Verbinden der Tabellen verwendeten Spalten automatisch berechnet werden, können die Ergebnisse bei einer Änderung der Spalten in den Komponententabellen aufgrund neuer Join-Bedingungen sehr unterschiedlich sein.
Join-Bedingungen und das WHERE
Klausel
Join-Bedingungen teilen viele Merkmale mit den Vergleichen, die zum Filtern von Datenzeilen mit WHERE
verwendet werden Klauseln. Beide Konstrukte definieren Ausdrücke, die als wahr ausgewertet werden müssen, damit die Zeile berücksichtigt wird. Aus diesem Grund ist es nicht immer intuitiv, was der Unterschied zwischen dem Einfügen zusätzlicher Vergleiche in ein WHERE
ist zu konstruieren, anstatt sie innerhalb der Join-Klausel selbst zu definieren.
Um die daraus resultierenden Unterschiede zu verstehen, müssen wir uns die Reihenfolge ansehen, in der PostgreSQL verschiedene Teile einer Abfrage verarbeitet. In diesem Fall werden die Prädikate in der Verknüpfungsbedingung zuerst verarbeitet, um die virtuelle verknüpfte Tabelle im Speicher zu erstellen. Nach dieser Phase werden die Ausdrücke innerhalb des WHERE
-Klausel werden ausgewertet, um die resultierenden Zeilen zu filtern.
Nehmen wir als Beispiel an, dass wir zwei Tabellen mit dem Namen customer
haben und order
dass wir uns zusammenschließen müssen. Wir wollen die beiden Tabellen verbinden, indem wir die customer.id
abgleichen Spalte mit der order.customer_id
Säule. Außerdem interessieren uns die Zeilen in der order
Tabelle, die eine product_id
haben von 12345.
Angesichts der oben genannten Anforderungen haben wir zwei Bedingungen, die uns wichtig sind. Die Art und Weise, wie wir diese Bedingungen ausdrücken, bestimmt jedoch die Ergebnisse, die wir erhalten.
Lassen Sie uns zunächst beide als Join-Bedingungen für einen LEFT JOIN
verwenden :
SELECT customer.id AS customer_id, customer.name, order.id AS order_id, order.product_idFROM customerLEFT JOIN orderON customer.id = order.customer_id AND order.product_id = 12345;
Die Ergebnisse könnten möglicherweise so aussehen:
customer_id | name | order_id | product_id ------------+----------+----------+------------ 4380 | Acme Co | 480 | 12345 4380 | Acme Co | 182 | 12345 320 | Other Co | 680 | 12345 4380 | Acme Co | | 320 | Other Co | | 20 | Early Co | | 8033 | Big Co | |(7 rows)
PostgreSQL kam zu diesem Ergebnis, indem es die folgenden Operationen ausführte:
- Kombinieren Sie beliebige Zeilen im
customer
Tabelle mit derorder
Tabelle wo:customer.id
stimmt mitorder.customer_id
überein .order.product_id
entspricht 12345
- Da wir eine Linksverknüpfung verwenden, schließen Sie alle nicht übereinstimmenden ein Zeilen aus der linken Tabelle (
customer
), die Spalten aus der rechten Tabelle auffüllen (order
) mitNULL
Werte. - Nur die in
SELECT
aufgelisteten Spalten anzeigen Spaltenspezifikation.
Das Ergebnis ist, dass alle unsere verbundenen Zeilen beide Bedingungen erfüllen, nach denen wir suchen. Der linke Join bewirkt jedoch, dass PostgreSQL auch alle Zeilen aus der ersten Tabelle enthält, die die Join-Bedingung nicht erfüllt haben. Dies führt zu "übrigen" Zeilen, die scheinbar nicht der offensichtlichen Absicht der Abfrage entsprechen.
Wenn wir die zweite Abfrage verschieben (order.product_id
=12345) zu einem WHERE
-Klausel, anstatt sie als Join-Bedingung einzufügen, erhalten wir andere Ergebnisse:
SELECT customer.id AS customer_id, customer.name, order.id AS order_id, order.product_idFROM customerLEFT JOIN orderON customer.id = order.customer_idWHERE order.product_id = 12345;
Diesmal werden nur drei Zeilen angezeigt:
customer_id | name | order_id | product_id ------------+----------+----------+------------ 4380 | Acme Co | 480 | 12345 4380 | Acme Co | 182 | 12345 320 | Other Co | 680 | 12345(3 rows)
Die Reihenfolge, in der die Vergleiche ausgeführt werden, ist der Grund für diese Unterschiede. Dieses Mal verarbeitet PostgreSQL die Abfrage wie folgt:
- Kombinieren Sie beliebige Zeilen im
customer
Tabelle mit derorder
Tabelle mitcustomer.id
stimmt mitorder.customer_id
überein . - Da wir eine Linksverknüpfung verwenden, schließen Sie alle nicht übereinstimmenden ein Zeilen aus der linken Tabelle (
customer
), die Spalten aus der rechten Tabelle auffüllen (order
) mitNULL
Werte. - Werten Sie das
WHERE
aus -Klausel, um alle Zeilen zu entfernen, die nicht 12345 als Wert fürorder.product_id
haben Spalte. - Nur die in
SELECT
aufgelisteten Spalten anzeigen Spaltenspezifikation.
Dieses Mal, obwohl wir einen linken Join verwenden, das WHERE
schneidet die Ergebnisse ab, indem alle Zeilen ohne die korrekte product_id
herausgefiltert werden . Weil alle nicht übereinstimmenden Zeilen product_id
haben würden auf NULL
gesetzt , entfernt dies alle nicht übereinstimmenden Zeilen, die von der linken Verknüpfung ausgefüllt wurden. Außerdem werden alle Zeilen entfernt, die mit der Join-Bedingung übereinstimmen, die diese zweite Überprüfungsrunde nicht bestanden haben.
Wenn Sie den grundlegenden Prozess verstehen, den PostgreSQL zur Ausführung Ihrer Abfragen verwendet, können Sie einige leicht zu machende, aber schwer zu behebende Fehler bei der Arbeit mit Ihren Daten vermeiden.
Fazit
In diesem Leitfaden haben wir behandelt, wie Verknüpfungen es relationalen Datenbanken ermöglichen, Daten aus verschiedenen Tabellen zu kombinieren, um wertvollere Antworten zu liefern. Wir sprachen über die verschiedenen Verknüpfungen, die PostgreSQL unterstützt, die Art und Weise, wie jeder Typ seine Ergebnisse zusammenstellt, und was zu erwarten ist, wenn bestimmte Arten von Verknüpfungen verwendet werden. Danach sind wir verschiedene Möglichkeiten zur Definition von Join-Bedingungen durchgegangen und haben uns angesehen, wie das Zusammenspiel zwischen Joins und dem WHERE
ist Klausel kann zu Überraschungen führen.
Verknüpfungen sind ein wesentlicher Bestandteil dessen, was relationale Datenbanken leistungsfähig und flexibel genug macht, um so viele verschiedene Arten von Abfragen zu verarbeiten. Das Organisieren von Daten mithilfe logischer Grenzen und gleichzeitig die Möglichkeit, die Daten von Fall zu Fall auf neuartige Weise neu zu kombinieren, verleiht relationalen Datenbanken wie PostgreSQL eine unglaubliche Vielseitigkeit. Wenn Sie lernen, wie Sie dieses Stitching zwischen Tabellen durchführen, können Sie komplexere Abfragen erstellen und sich darauf verlassen, dass die Datenbank vollständige Bilder Ihrer Daten erstellt.