SQL-Joins und Tabellenbeziehungen
AnfängerEinheit 5 von 6 in Kurs: SQL – Datenbanken abfragen mit SELECT, JOIN und GROUP BY
Was du lernst
- Lies, wie Tabellen durch Schlüssel verbunden sind, und erkläre, was ein Join mit ihren Zeilen macht, bevor du selbst einen schreibst.
- Die Verknüpfungen zwischen Tabellen in einem Schema findenErkenne anhand von Primär- und Fremdschlüsseln, wie Tabellen zusammenhängen, benenne jede Beziehung als Eins-zu-eins-, Eins-zu-viele- oder Viele-zu-viele-Beziehung und plane, welche Spalten ein Join abgleichen soll.
- Erklären, was ein Join mit Zeilen machtBeschreibe einen Join als Paarung von Zeilen, die eine Bedingung erfüllen, sage die Breite und Länge des Ergebnisses voraus und verwende Tabellenaliase und qualifizierte Spaltennamen.
- Die Verknüpfungen zwischen Tabellen in einem Schema finden
- Schreibe Inner Joins mit ON, USING und Bereichsbedingungen, die nur Zeilen mit einem Partner in beiden Tabellen zurückgeben, und filtere und sortiere die kombinierten Zeilen.
- Einen Inner Join mit ON schreibenVerknüpfe zwei Tabellen mit JOIN ... ON über ihre Schlüsselspalten, sage genau voraus, welche Zeilen zurückgegeben werden, und ergänze Filter, Sortierung und klare Spaltennamen.
- USING, NATURAL JOIN, Komma-Joins und Bereichsbedingungen verwendenErkenne andere Schreibweisen für einen Inner Join, erkläre das Risiko jeder Variante und verknüpfe Zeilen anhand eines Bereichs statt eines gleichen Schlüsselwerts.
- Einen Inner Join mit ON schreiben
- Verwende Left, Right und Full Outer Joins, um Zeilen ohne Partner zu erhalten und fehlende Daten zu finden. Platziere jede Bedingung so, dass sie wie beabsichtigt filtert.
- Mit LEFT JOIN alle Zeilen einer Tabelle erhaltenSchreibe einen Left Outer Join, sage seine mit NULL aufgefüllten Zeilen voraus und finde damit Zeilen ohne Partner in einer anderen Tabelle.
- RIGHT JOIN und FULL OUTER JOIN verwendenErhalte Zeilen ohne Partner aus der rechten oder aus beiden Tabellen, schreibe einen Right Join als Left Join um und vergleiche mit einem Full Join zwei Listen.
- Bedingungen richtig in ON oder WHERE platzierenErkläre, warum sich eine Bedingung in ON und WHERE bei einem Outer Join unterschiedlich verhält, und wähle für jede Bedingung die richtige Stelle.
- Mit LEFT JOIN alle Zeilen einer Tabelle erhalten
- Verwende Self Joins, um Zeilen innerhalb einer Tabelle in Beziehung zu setzen, bilde mit Cross Joins alle Kombinationen und erkenne unbeabsichtigte Cross Joins.
- Zeilen derselben Tabelle mit einem Self Join in Beziehung setzenVerknüpfe eine Tabelle über zwei Aliase mit sich selbst, um Verweisen innerhalb der Tabelle zu folgen, etwa von Mitarbeitern zu ihren Vorgesetzten, und um Zeilen derselben Tabelle zu paaren.
- Alle Kombinationen mit einem Cross Join bildenPaare mit CROSS JOIN jede Zeile einer Tabelle mit jeder Zeile einer anderen, sage die Größe des Ergebnisses voraus und erkenne unbeabsichtigte kartesische Produkte.
- Zeilen derselben Tabelle mit einem Self Join in Beziehung setzen
- Beantworte mit Zwischentabellen Fragen zu Viele-zu-viele-Beziehungen und verknüpfe drei oder mehr Tabellen in einer Abfrage, wobei du bei jedem Schritt die richtigen Zeilen erhältst.
- Viele-zu-viele-Beziehungen über eine Zwischentabelle abfragenErkläre, wie eine Zwischentabelle zwei Tabellen verbindet, und verknüpfe Tabellen über sie, um Fragen in beide Richtungen zu beantworten, auch mit Zeilen ohne Partner.
- Drei oder mehr Tabellen in einer Abfrage verknüpfenPlane einen Schlüsselpfad über mehrere Tabellen, schreibe einen Join pro Verknüpfung und lies ab, wofür jede Zeile eines Ergebnisses aus mehreren Tabellen steht.
- Zeilen ohne Partner über eine Join-Kette hinweg erhaltenKombiniere Outer und Inner Joins in einer Kette, ohne Zeilen zu verlieren, die du erhalten wolltest, und prüfe jeden Schritt der Kette.
- Viele-zu-viele-Beziehungen über eine Zwischentabelle abfragen
- Erkenne, wann ein Join Zeilen vervielfacht oder verliert, behebe überhöhte Anzahlen und Summen und prüfe ein Join-Ergebnis, bevor du ihm vertraust.
- Vervielfachte Zeilen und überhöhte Summen behebenErkläre, warum Joins entlang von Eins-zu-viele-Verknüpfungen Zeilen wiederholen, und zähle und summiere Werte auf der richtigen Ebene, damit die Ergebnisse korrekt bleiben.
- Ein Join-Ergebnis prüfen, bevor du ihm vertraustSage voraus, wie viele Zeilen ein Join zurückgeben sollte, erkenne die Anzeichen häufiger Join-Fehler und gehe für jede Join-Abfrage eine kurze Prüfliste durch.
- Vervielfachte Zeilen und überhöhte Summen beheben
SQL-Joins einfach erklärt
1Schlüssel und kombinierte Zeilen
Ein Join beginnt mit einer Beziehung zwischen Zeilen. Kunden- und Bestelldaten stehen in getrennten Tabellen, und Schlüssel zeigen dir, wie du sie zusammenführst. Lies das kleine Ladenschema, unterscheide Eins-zu-eins-, Eins-zu-viele- und Viele-zu-viele-Verknüpfungen und verfolge einen Pfad für einen Bericht. Sieh dann nach, wie aus passenden Paaren Ergebniszeilen werden, warum sich Namen wiederholen können und wie Aliase die Herkunft jeder ausgewählten Spalte verdeutlichen.
1.1 Schlüssel und Pfade zwischen Tabellen
Die Adresse eines Kunden gehört zum Kunden. Das Datum einer Bestellung gehört zur Bestellung. Diese Fakten in getrennten Tabellen zu speichern, verringert Wiederholungen, doch ein Bericht braucht oft Fakten aus beiden Tabellen. Ein Join verknüpft ihre Zeilen innerhalb einer Abfrage.
Schlüssel lesen
Ein Primärschlüssel identifiziert eine Zeile. Er kann aus einer Spalte oder mehreren Spalten zusammen bestehen. Ein Fremdschlüssel verweist auf einen Primärschlüssel oder einen anderen eindeutigen Schlüssel, entweder in einer anderen oder in derselben Tabelle. In der Ladendatenbank zeigt orders.customer_id auf customers.customer_id.
| customer_id | name | city |
|---|---|---|
| 1 | Ana | Denver |
| 2 | Ben | Austin |
| 3 | Chloe | Denver |
| 4 | Dev | Boston |
| order_id | customer_id | order_date | total |
|---|---|---|---|
| 101 | 1 | 2026-03-02 | 22,00 |
| 102 | 1 | 2026-03-15 | 25,50 |
| 103 | 2 | 2026-03-20 | 60,00 |
| 104 | NULL | 2026-03-21 | 15,00 |
Die Bestellungen 101 und 102 verweisen beide auf Kunde 1, Ana. Bestellung 103 verweist auf Ben. Bestellung 104 ist eine Gastbestellung: Ihr Kundenschlüssel ist NULL, sie verweist also auf keinen Kunden. Die Bestellnummer identifiziert die Bestellung, nicht den Kunden. Ein Join von order_id mit customer_id würde Kennungen vergleichen, die nichts miteinander zu tun haben.
Die Beziehung benennen
| Beziehung | Bedeutung | Wo die Verknüpfung steht |
|---|---|---|
| Eins zu eins | Jede Zeile hat höchstens einen Partner auf der anderen Seite. | Ein Fremdschlüssel ist ebenfalls eindeutig, wie bei einem Ausweis pro Mitarbeiter. |
| Eins zu viele | Eine Elternzeile kann mehrere Kindzeilen haben; jede Kindzeile hat höchstens eine Elternzeile. | Der Fremdschlüssel steht auf der Viele-Seite, wie in orders. |
| Viele zu viele | Zeilen auf beiden Seiten können mehrere Partner haben. | Eine Zwischentabelle enthält je einen Fremdschlüssel zu jeder Seite. |
Die Beziehung zwischen Kunden und Bestellungen ist eine Eins-zu-viele-Beziehung. Ein Kunde kann keine, eine oder mehrere Bestellungen haben. Das bedeutet nicht, dass die Kundentabelle für jeden Kauf eine Bestell-ID speichert. Jede Bestellung speichert ihren eigenen Kundenverweis.
Bei Studierenden und Kursen kann keine Seite alle Verknüpfungen mit nur einem Verweis beschreiben. Eine Zeile in enrollments erfasst ein Paar aus Studierendem und Kurs. Mehrere Einschreibungszeilen können auf denselben Studierenden und mehrere auf denselben Kurs verweisen.
Vor dem Schreiben von SQL einen Pfad verfolgen
Um die von jedem Kunden gekauften Produkte aufzulisten, folge customers → orders → order_items → products. Die Verknüpfungen verwenden zunächst customer_id, dann order_id und dann product_id. Jede Verknüpfung braucht ihre eigene Bedingung. Eine Bestellposition liefert die fehlende Verbindung zwischen einer Bestellung und einem Produkt.
Lies die Bedeutung des Schemas, nicht nur die Schreibweise der Spalten. employees.manager_id kann auf employees.emp_id verweisen, obwohl sich die Namen unterscheiden. Umgekehrt bezeichnen customers.name und products.name unterschiedliche Arten von Dingen und sollten nicht nur deshalb abgeglichen werden, weil beide name heißen.
Ein deklarierter Fremdschlüssel ist ein hilfreicher Wegweiser, aber SQL kann Tabellen auch ohne deklarierte Integritätsbedingung verknüpfen. Ein Preis kann zu einem Preisbereich passen, und zwei Mitarbeiter können zusammenpassen, weil sie denselben Vorgesetzten haben. Die Bedingung muss die für die Frage benötigte Beziehung ausdrücken.
Wichtige Erkenntnisse
- Ein Primärschlüssel identifiziert eine Zeile; ein Fremdschlüssel verweist auf einen Primärschlüssel oder einen eindeutigen Schlüssel.
- Der Fremdschlüssel steht auf der Viele-Seite einer Eins-zu-viele-Beziehung.
- Eine Zwischentabelle erfasst die Paare einer Viele-zu-viele-Beziehung.
- Folge den Verknüpfungen im Schema und gib jeder Verknüpfung eine sinnvolle Bedingung.
1.2 Wie passende Zeilen zu einem Ergebnis werden
Ein Join bildet neue Zeilen, indem er Eingabezeilen kombiniert. Beginne mit der Abgleichsregel und frag dich dann, wie viele Partner jede Zeile hat. Die Antwort bestimmt sowohl, welche Zeilen erscheinen, als auch, wie oft sich ihre Werte wiederholen.
In Paaren denken
Stelle dir bei einem Inner Join jeden Kunden neben jeder Bestellung vor. Behalte ein Paar nur, wenn o.customer_id = c.customer_id wahr ist. Bestellung 101 wird mit Ana gepaart, aber nicht mit Ben, Chloe oder Dev. Auch Bestellung 102 wird mit Ana gepaart. Ein Kunde kann daher mehrere Ergebniszeilen beitragen.
Die Bedingung kann wahr, falsch oder unbekannt sein. Eine Gleichheitsbedingung mit NULL ist unbekannt, sodass Gastbestellung 104 keinen passenden Kunden findet. Ein Outer Join erhält zusätzlich Zeilen ohne Partner von seiner gewählten Seite und füllt die Spalten des fehlenden Partners mit NULL.
Diese Vorstellung von Paaren erklärt Joins besser als überlappende Kreise. Ein Join sammelt nicht nur gemeinsame Elemente: Er bildet kombinierte Zeilen, und wiederholte Schlüssel können mehr Ergebniszeilen erzeugen, als jede der Eingaben enthält. Haben zwei Zeilen auf einer Seite und drei auf der anderen denselben Schlüssel, ergeben sich für diesen Schlüssel sechs passende Paare.
Spalten unabhängig von den Treffern auswählen
Die Kundentabelle des Ladens hat drei Spalten und die Bestelltabelle vier. Bei JOIN ... ON gibt SELECT * alle sieben zurück, einschließlich beider Exemplare von customer_id. Du kannst stattdessen nur die Felder auswählen, die der Bericht braucht:
SELECT c.name, o.order_id, o.total
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id
ORDER BY o.order_id;
Das Ergebnis ist (Ana; 101; 22,00), (Ana; 102; 25,50) und (Ben; 103; 60,00). Die Schlüsselspalten ermöglichen den Abgleich, ohne in der ausgewählten Ausgabe erscheinen zu müssen. Weniger Spalten auszuwählen verändert die Breite des Ergebnisses, aber nicht, welche Eingabepaare zusammenpassen.
Tabellen kurze, klare Namen geben
In FROM customers c ist c ein Tabellenalias. Sprich die Spalten dieser Tabelle als c.name und c.customer_id an. Der Ausdruck c.name ist ein qualifizierter Spaltenname: Der Teil vor dem Punkt gibt an, welche Tabellenrolle den Wert liefert.
Beide verknüpften Tabellen enthalten customer_id. Schreibst du bei der Form mit ON nur SELECT customer_id, kann die Datenbank nicht zwischen ihnen wählen und meldet einen Fehler wegen einer mehrdeutigen Spalte. Schreibe c.customer_id oder o.customer_id, je nachdem, welchen Wert du brauchst. Qualifizierst du auch andere ausgewählte Spalten, ist ihre Herkunft ebenfalls leicht erkennbar.
AS vor einem Tabellenalias ist in PostgreSQL, SQLite, MySQL und SQL Server optional. Oracle akzeptiert es nicht, daher ist FROM customers c eine nützliche gemeinsame Schreibweise. Nachdem du einer Tabelle einen Alias gegeben hast, verwende diesen konsequent.
Die logische Reihenfolge der Abfrage lesen
FROM und seine Joins bilden die kombinierten Zeilen. WHERE filtert diese Zeilen. SELECT wählt die Ergebnisspalten aus und ORDER BY sortiert das Ergebnis. Ein Filter kann eine verknüpfte Spalte verwenden, auch wenn diese nicht ausgewählt ist. Beispielsweise kann WHERE c.city = 'Denver' einen Bericht filtern, der nur Namen und Bestellsummen anzeigt.
Ohne ORDER BY garantiert die Datenbank keine bestimmte Zeilenreihenfolge. Eine Abfrage, die heute Ana zuerst anzeigt, kann später eine andere Zeile zuerst anzeigen; das Sortieren ist eine eigene Anweisung und vom Abgleich getrennt.
Wichtige Erkenntnisse
- Ein Inner Join erhält jedes Paar, dessen Bedingung wahr ist.
- Wiederholte Schlüsselwerte können für eine Eingabezeile mehrere Zeilen erzeugen.
- Aliase und qualifizierte Namen zeigen, welche Tabelle eine Spalte liefert.
- Joins bilden Zeilen, bevor
WHEREsie filtert undSELECTSpalten auswählt. - Verwende
ORDER BY, wenn die Zeilenreihenfolge wichtig ist.
2Inner Joins schreiben
Inner Joins beantworten Fragen, für die passende Fakten auf beiden Seiten nötig sind, etwa der Name eines Kunden neben einer Bestellung. Formuliere eine ausdrückliche Bedingung, sieh dir die tatsächlichen Ergebniszeilen an und ergänze Filter und Sortierung. Lies anschließend die Kurzformen und älteren Formen, die dir in bestehenden Abfragen begegnen können. Der Abgleich mit Bereichen führt eine andere Art von Bedingung ein: Überlappende Bereiche oder Lücken können verändern, wie viele Zeilen jeder Wert erzeugt.
2.1 Passende Zeilen mit JOIN und ON verknüpfen
Verwende einen Inner Join, wenn eine Ergebniszeile einen Partner in beiden Tabellen braucht. JOIN und INNER JOIN bedeuten dasselbe. Beide erhalten keine Zeile, die keinen Partner findet.
Die Abfrage in drei Teilen aufbauen
Benenne zuerst die Tabellen und ihre Rollen. Gib dann die Beziehung in ON an. Wähle schließlich die anzuzeigenden Spalten aus.
SELECT c.name, o.order_id, o.total
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id
ORDER BY o.order_id;
Lies die Bedingung als „Der Kundenverweis der Bestellung entspricht der Kennung dieses Kunden“. Für Bestellung 101 ist der Verweis 1, sie wird also mit Ana gepaart. Auch Bestellung 102 hat den Verweis 1, und Bestellung 103 hat den Verweis 2. Das vollständige Ergebnis lautet:
| name | order_id | total |
|---|---|---|
| Ana | 101 | 22,00 |
| Ana | 102 | 25,50 |
| Ben | 103 | 60,00 |
Ana erscheint zweimal, weil sie zwei passende Bestellungen hat. Chloe und Dev haben keine und erscheinen daher nicht. Gastbestellung 104 hat einen Kundenverweis NULL, der keine Gleichheitsbedingung mit einem Kundenschlüssel erfüllt.
Die kombinierten Zeilen filtern und sortieren
Um nur Kunden aus Denver anzuzeigen, setze WHERE c.city = 'Denver' nach den Join und vor ORDER BY. Das Ergebnis lautet dann (Ana; 101; 22,00) und (Ana; 102; 25,50). Auch Chloe wohnt in Denver, aber der Inner Join hat für sie keine Zeile erzeugt.
Bei einem Inner Join ergeben sich dieselben Paare, wenn dieser Filter in ON steht. Eine gut lesbare Konvention ist, Bedingungen für den Tabellenabgleich in ON und Berichtsfilter in WHERE zu belassen. Für Outer Joins gilt diese Gleichwertigkeit nicht.
Du kannst nach einer verknüpften Spalte sortieren, die in der ausgewählten Ausgabe fehlt. Du kannst auch die Join-Schlüssel in der Ausgabe weglassen: Die obige Abfrage gleicht über customer_id ab und zeigt dabei einen Namen, eine Bestellnummer und eine Summe an. Die Rolle einer Spalte beim Abgleich ist von ihrer Rolle im Bericht getrennt.
Alle Teile eines Schlüssels abgleichen
Manche Datensätze werden durch ein Spaltenpaar identifiziert. Eine Versandposition, die auf eine Bestellposition verweist, benötigt möglicherweise sowohl die Bestell- als auch die Produktkennung:
SELECT s.order_id, s.product_id, oi.quantity
FROM shipment_lines s
JOIN order_items oi
ON s.order_id = oi.order_id
AND s.product_id = oi.product_id;
Beide Vergleiche müssen für einen Treffer wahr sein. Ein Abgleich nur über order_id würde jede Versandposition mit jeder Produktposition dieser Bestellung verbinden. Die Abfrage könnte erfolgreich laufen und dabei die falschen Produktmengen beschreiben.
Die Reihenfolge ändern, ohne die Bedeutung zu ändern
FROM orders o JOIN customers c ON c.customer_id = o.customer_id liefert dieselben Kunden-Bestellungs-Paare. Auch das Vertauschen der beiden Seiten von = erhält eine Gleichheitsbedingung. SELECT * kann die Spalten nach einem Tausch der Tabellen anders anordnen, und die Zeilenreihenfolge bleibt ohne Sortierung unbestimmt.
Eine weit schwerwiegendere Änderung ist ON o.order_id = c.customer_id. Beide Spalten enthalten Zahlen, daher ist dies zulässiges SQL, aber sie identifizieren unterschiedliche Dinge. In den Ladendaten gibt die Abfrage null Zeilen zurück: Die Bestell-IDs 101–104 entsprechen nie den Kunden-IDs 1–4. Prüfe die Beziehung im Schema auch dann, wenn die Datenbank keinen Syntaxfehler meldet.
Wichtige Erkenntnisse
JOINbedeutetINNER JOIN: Zeilen ohne Partner auf beiden Seiten werden ausgeschlossen.- Schreibe die Beziehung in
ONund ergänze dann Berichtsfilter und Sortierung. - Gleiche alle Teile eines zusammengesetzten Schlüssels mit
ANDab. - Auch zulässiges SQL kann die falschen Spalten abgleichen.
2.2 Andere Möglichkeiten, einen Abgleich anzugeben
ON nennt eine Bedingung ausdrücklich, aber in bestehendem SQL können kürzere oder ältere Formen stehen. Lies jede Form mit der Frage, welche Paare sie erhält. Manche Formen ändern auch, wie gemeinsame Spalten in der Ausgabe erscheinen.
USING nennt den gemeinsamen Schlüssel
Wenn die Schlüsselspalten denselben Namen haben, verwendet diese Abfrage eine verkürzte Gleichheitsbedingung:
SELECT c.name, o.order_id
FROM customers c
JOIN orders o USING (customer_id)
ORDER BY o.order_id;
Sie gibt (Ana, 101), (Ana, 102) und (Ben, 103) zurück. USING (customer_id) bedeutet, die beiden Spalten customer_id zu vergleichen. Mit SELECT * gibt die Abfrage sechs Spalten zurück und zeigt den gemeinsamen Schlüssel einmal; JOIN ... ON enthält beide Schlüsselspalten der Eingaben.
Für einen zusammengesetzten Schlüssel liste beide Namen auf: USING (order_id, product_id). Jede aufgeführte Spalte muss unter diesem Namen in beiden Eingaben existieren.
PostgreSQL, SQLite, MySQL und Oracle unterstützen USING, SQL Server nicht. In Oracle darf eine in USING genannte Spalte bei einem Verweis nicht qualifiziert werden. Schreibe also SELECT customer_id, nicht SELECT c.customer_id. Andere Spalten können weiterhin ihre Tabellenaliase verwenden.
NATURAL JOIN wählt Spalten für dich
Ein NATURAL JOIN vergleicht alle Spaltennamen, die die Eingaben gemeinsam haben, verbindet diese Gleichheitsprüfungen mit AND und zeigt die gemeinsamen Spalten einmal an. PostgreSQL, SQLite, MySQL und Oracle unterstützen ihn, SQL Server nicht.
Diese automatische Wahl kann eine Abfrage unbemerkt verändern. Kunden und Bestellungen haben derzeit nur customer_id gemeinsam. Kommt zu orders eine Spalte city hinzu, verlangt ein Natural Join, dass sowohl Kunden-ID als auch Stadt übereinstimmen. Unterscheidet sich der Lieferort vom Wohnort des Kunden, kann eine zuvor passende Bestellung dadurch entfallen.
Kunden und Produkte haben beide name, aber die eine Spalte bezeichnet eine Person, die andere ein Produkt. Ihr Natural Join würde diese nicht zusammengehörigen Namen vergleichen und gibt in den Ladendaten keine Zeilen zurück. Ohne gemeinsame Spaltennamen gibt ein Natural Join stattdessen jede Kombination zurück. Verwende ON oder eine bewusst gewählte USING-Liste, damit die Abgleichsregel sichtbar bleibt.
Ältere Komma-Joins lesen
SELECT c.name, o.order_id
FROM customers c, orders o
WHERE o.customer_id = c.customer_id;
Dies gibt dieselben drei Paare wie der Inner Join zurück. Die Bedingung steht nun in WHERE. Vergisst du sie, werden alle vier Kunden mit allen vier Bestellungen gepaart, sodass 16 Zeilen entstehen. JOIN ... ON hält jede Tabelle neben ihrer eigenen Bedingung, wodurch längere Abfragen leichter zu prüfen sind.
Einen Wert mit einem Bereich abgleichen
Ein Equi-Join verwendet eine Gleichheitsbedingung. Ein Non-Equi-Join verwendet einen anderen Vergleich, etwa eine Bereichsprüfung:
SELECT p.name, b.band
FROM products p
JOIN price_bands b
ON p.price BETWEEN b.min_price AND b.max_price;
Die Bereiche sind Budget 0,00–4,99, Standard 5,00–19,99 und Premium 20,00–999,99. Mug für 8,00 und Stapler für 12,00 passen zu Standard; Pen für 1,50 und Notebook für 4,25 passen zu Budget. Premium hat kein passendes Produkt und trägt keine Zeile bei.
BETWEEN schließt beide Bereichsgrenzen ein. Ein neuer Bereich Gift von 8,00 bis 15,00 würde für Mug und Stapler jeweils einen zweiten Treffer ergeben. Durch die Lücke zwischen 4,99 und 5,00 hätte ein Preis von 4,995 keinen Partner. Bereiche bestimmen das Ergebnis ebenso wie Schlüssel: Ein Wert kann keinen, einen oder mehrere Partner haben.
Wichtige Erkenntnisse
USINGvergleicht die aufgeführten gleichnamigen Spalten und zeigt jeden gemeinsamen Schlüssel einmal an.NATURAL JOINhängt von jedem gemeinsamen Spaltennamen ab, sodass Schemaänderungen sein Ergebnis verändern können.- Ein Komma-Join braucht seine Abgleichsbedingung in
WHERE. - Ein Non-Equi-Join kann Bereiche abgleichen; Überlappungen erzeugen zusätzliche Treffer und Lücken lassen Werte ohne Partner.
- SQL Server verwendet
ONund bietet keine Syntax fürUSINGoderNATURAL JOIN.
3Zeilen ohne Partner erhalten
In Berichten müssen fehlende Beziehungen oft sichtbar bleiben: Kunden ohne Bestellungen, unverkaufte Produkte oder Datensätze, die in einer von zwei Listen fehlen. Outer Joins erhalten diese Zeilen und kennzeichnen den fehlenden Partner mit NULL-Werten. Wähle, welche Seite erhalten bleiben muss, und verfolge dann, wie Bedingungen das Ergebnis verändern, je nachdem, ob sie beim Abgleich oder danach angewendet werden. Die Position einer Datumsprüfung kann darüber entscheiden, ob ein Kunde vollständig verschwindet.
3.1 Alle Zeilen von links, auch ohne Partner
Ein Bericht über „alle Kunden, einschließlich Kunden ohne Bestellungen“ braucht einen Left Outer Join. LEFT JOIN erhält jede linke Zeile. Er fügt jede passende rechte Zeile hinzu oder liefert eine Zeile mit NULL-Werten, wenn es keinen Partner gibt. Das Wort OUTER ist optional.
Der erhaltenen Tabelle folgen
SELECT c.name, o.order_id, o.total
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
ORDER BY c.customer_id, o.order_id;
| name | order_id | total |
|---|---|---|
| Ana | 101 | 22,00 |
| Ana | 102 | 25,50 |
| Ben | 103 | 60,00 |
| Chloe | NULL | NULL |
| Dev | NULL | NULL |
Ana liefert weiterhin zwei Zeilen. Ein Left Join reduziert die Bestellungen eines Kunden nicht auf eine. Chloe und Dev liefern jeweils genau eine Zeile, weil keiner von beiden einen Partner hat. Insgesamt gibt es fünf Zeilen: drei passende Paare und zwei Kunden ohne Partner.
Vor späteren Filtern gibt der Join mindestens so viele Zeilen zurück, wie seine linke Eingabe enthält. Zähle für jede linke Zeile ihre Partner; hat sie keine, zähle eine mit NULL aufgefüllte Zeile. Das erklärt, warum vier Kunden fünf Zeilen ergeben können.
Gastbestellung 104 fehlt. Alle Kunden zu erhalten, erhält nicht auch Bestellungen ohne Partner. Um jede Bestellung zu erhalten, beginne mit orders o LEFT JOIN customers c ON c.customer_id = o.customer_id. Die Auswahl von o.order_id, c.name ergibt dann (101, Ana), (102, Ana), (103, Ben) und (104, NULL). Chloe und Dev erscheinen nicht mehr.
Zeilen ohne Partner finden
Ein linker Anti-Join erhält nur Zeilen, für die kein Partner gefunden wurde:
SELECT c.name
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
WHERE o.order_id IS NULL;
Der Left Join bildet zunächst alle fünf Zeilen. WHERE erhält dann Chloe und Dev, deren Bestellschlüssel NULL sind. Ihr fehlender Partner ist genau das, wonach die Abfrage sucht.
Wähle eine Spalte der rechten Seite, die bei einem tatsächlichen Treffer nicht NULL sein kann. Der Primärschlüssel einer Bestellung eignet sich gut für die Prüfung. Die Prüfung eines optionalen coupon_code würde auch tatsächlich passende Bestellungen ohne Gutschein erhalten und hätte daher nicht die Bedeutung „keine Bestellung“. Verwende IS NULL: = NULL wird als unbekannt ausgewertet und erhält in WHERE keine Zeilen.
Dasselbe Muster findet unverkaufte Produkte:
SELECT p.name
FROM products p
LEFT JOIN order_items oi ON oi.product_id = p.product_id
WHERE oi.order_id IS NULL;
Die Abfrage gibt (Stapler) zurück, das einzige Produkt ohne Bestellposition. Hier hat eine tatsächlich passende Position notwendigerweise eine Bestellkennung, sodass die Prüfung die fehlende Position erkennt.
Einen fehlenden Wert vor dem Ersetzen deuten
Eine mit NULL aufgefüllte Zeile eines Outer Joins bedeutet, dass kein Partner gefunden wurde. Ein gespeichertes NULL in einer tatsächlichen Bestellung kann dagegen bedeuten, dass ein Feld nicht ausgefüllt wurde. Das sind unterschiedliche Situationen, obwohl beide als NULL angezeigt werden.
COALESCE(o.total, 0) wählt das erste Argument, das nicht NULL ist. Für Chloe und Dev würde die Funktion 0 anzeigen. Das kann für einen Bericht über Ausgaben hilfreich sein, aber eine Null in einer Spalte mit der Bezeichnung „Bestellsumme“ kann eine tatsächliche Bestellung über null nahelegen. Achte darauf, dass Bezeichnung und Bedeutung des Berichts zusammenpassen.
Wichtige Erkenntnisse
- Ein Left Join erhält die linken Zeilen und liefert NULL-Werte für fehlende rechte Partner.
- Zähle jedes passende Paar sowie eine Zeile für jede linke Zeile ohne Partner.
- Verwende für einen Anti-Join
WHERE right_key IS NULLmit einem Schlüssel, der bei einem Treffer nicht NULL sein kann. - Ein Left Join erhält eine rechte Zeile ohne Partner nicht.
COALESCEkann die Anzeige fehlender Werte ändern; wähle eine Bezeichnung, die ihre Bedeutung klar hält.
3.2 Die rechte Seite oder beide Seiten erhalten
Manchmal stehen die benötigten Zeilen rechts in einem Join. Manchmal müssen beide Eingaben erhalten bleiben, damit fehlende Datensätze verglichen werden können. Right und Full Outer Joins machen diese Wahl ausdrücklich.
Einen Right Join als Left Join schreiben
SELECT c.name, o.order_id
FROM customers c
RIGHT JOIN orders o ON o.customer_id = c.customer_id;
Dies erhält jede Bestellung: (Ana, 101), (Ana, 102), (Ben, 103) und (NULL, 104). Die rechte Tabelle ist orders, also bleibt die Gastbestellung erhalten. Chloe und Dev sind linke Zeilen ohne Partner und bleiben nicht erhalten.
Durch Vertauschen der Eingaben erhältst du das gleichwertige orders o LEFT JOIN customers c ON o.customer_id = c.customer_id. Dieselbe ausdrückliche SELECT-Liste liefert dieselben Werte. Bei SELECT * kann sich die standardmäßige Spaltenreihenfolge ändern. Verwendest du in einem Bericht durchgehend Left Joins, lässt sich die Seite, die erhalten bleiben muss, oft leichter verfolgen.
Fehlende Zeilen aus beiden Eingaben erhalten
SELECT c.name, o.order_id
FROM customers c
FULL OUTER JOIN orders o ON o.customer_id = c.customer_id;
Das Ergebnis enthält (Ana, 101), (Ana, 102), (Ben, 103), (Chloe, NULL), (Dev, NULL) und (NULL, 104). Das sind drei passende Paare, zwei Kunden ohne Partner und eine Bestellung ohne Partner: sechs Zeilen. Bei Gastbestellung 104 sind die Kundenspalten NULL; bei Chloe und Dev sind die Bestellspalten NULL.
| Join | Erhaltene Zeilen ohne Partner |
|---|---|
| LEFT JOIN | Nur linke Eingabe |
| RIGHT JOIN | Nur rechte Eingabe |
| FULL OUTER JOIN | Beide Eingaben |
Ein Full Join ist für den Abgleich nützlich, etwa um eine Lagerbestandsliste mit einer Inventur zu vergleichen. Passende Schlüssel erscheinen zusammen; Schlüssel, die nur auf einer Seite vorkommen, bleiben sichtbar. Ergänzt du die Ladenabfrage um WHERE c.customer_id IS NULL OR o.order_id IS NULL, bleiben nur Chloe, Dev und Bestellung 104 erhalten.
Beim Abgleich zweier Listen mit derselben Art von Schlüssel kann jeder der Eingabeschlüssel in der Ausgabe NULL sein. COALESCE(w.sku, k.sku) AS sku wählt die vorhandene Artikelnummer aus dem Lageralias w oder dem Alias k der Inventurliste. Mit einer zusammengeführten Schlüsselspalte kann der Bericht Datensätze identifizieren, die in einer der beiden Listen fehlen.
Die Syntaxunterstützung prüfen
PostgreSQL, SQL Server und Oracle unterstützen Right und Full Outer Joins. SQLite unterstützt beide ab Version 3.39.0, die 2022 veröffentlicht wurde. Ältere SQLite-Versionen lehnen sie ab. MySQL unterstützt Right Joins, hat aber keinen FULL OUTER JOIN; eine Umgehungslösung kombiniert Ergebnisse von Left und Right Joins mit UNION.
Älteres Oracle-SQL kann stattdessen die optionale Seite mit (+) in WHERE kennzeichnen. Beispielsweise erhält WHERE c.customer_id = o.customer_id(+) die Kunden und füllt fehlende Bestellspalten mit NULL, wie ein Left Join ausgehend von customers. Die Markierung gehört zu der Seite, die fehlen darf. Verwende beim Schreiben neuer Abfragen die benannten Join-Formen LEFT, RIGHT und FULL.
Wichtige Erkenntnisse
- Ein Right Join wird zu einem Left Join, wenn die Tabellen die Plätze tauschen.
- Die Zeilen eines Full Joins bestehen aus passenden Paaren und Zeilen ohne Partner von beiden Seiten.
- Ein Full Join kann beim Abgleich Einträge ohne Partner sichtbar machen.
- SQLite braucht für Right und Full Joins Version 3.39.0 oder neuer; MySQL hat kein Schlüsselwort für Full Joins.
3.3 Entscheiden, ob eine Bedingung in ON oder WHERE gehört
Ein Outer Join trennt zwei Entscheidungen: welche Paare als passend gelten und welche fertigen Ergebniszeilen der Bericht erhält. ON trifft die erste Entscheidung. WHERE trifft die zweite, nachdem Zeilen ohne Partner NULL-Werte erhalten haben.
Alle erhalten, aber ihre passenden Bestellungen einschränken
Angenommen, ein Bericht benötigt alle Kunden und nur ihre Bestellungen ab dem 10. März:
SELECT c.name, o.order_id
FROM customers c
LEFT JOIN orders o
ON o.customer_id = c.customer_id
AND o.order_date >= '2026-03-10';
Die Datumsprüfung ist Teil des Abgleichs. Anas Bestellung 101 ist zu früh, aber Bestellung 102 erfüllt die Bedingung. Bens Bestellung 103 erfüllt sie ebenfalls. Chloe und Dev haben keinen Partner, der die Bedingung erfüllt, und erhalten daher jeweils eine mit NULL aufgefüllte Zeile. Das Ergebnis ist (Ana, 102), (Ben, 103), (Chloe, NULL) und (Dev, NULL).
Die Zeilen nach dem Join filtern
Verschiebe dieselbe Datumsprüfung nach WHERE:
SELECT c.name, o.order_id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
WHERE o.order_date >= '2026-03-10';
Nun erzeugt der Join zunächst fünf Zeilen, darunter die mit NULL aufgefüllten Zeilen für Chloe und Dev. Der Datumsvergleich ist für diese NULL-Werte unbekannt, daher entfernt WHERE sie. Auch Anas frühe Bestellung wird entfernt. Nur (Ana, 102) und (Ben, 103) bleiben erhalten.
Die WHERE-Version erzeugt dieselben passenden Zeilen wie ein Inner Join mit diesem Datumsfilter.
Die erhaltene Tabelle gezielt filtern
Auch eine linksseitige Bedingung in ON kann keine linken Zeilen entfernen. Betrachte ON o.customer_id = c.customer_id AND c.city = 'Denver'. Ana kann zu beiden Bestellungen passen, Chloe hat keine, und Ben und Dev erfüllen bei keinem möglichen Paar den Stadtteil der Bedingung. Alle vier Kunden bleiben erhalten, bei Ben, Chloe und Dev mit NULL in den Bestellspalten.
Um nur Kunden aus Denver abzufragen, setze WHERE c.city = 'Denver' nach die gewöhnliche Schlüsselbedingung. Das Ergebnis ist (Ana, 101), (Ana, 102) und (Chloe, NULL). Chloe bleibt erhalten, weil der Filter ihre eigene Stadt prüft und nicht ein fehlendes Bestellfeld.
| Was die Bedingung tun soll | Typische Stelle in einem Left Join |
|---|---|
| Zulässige Partner auf der rechten Seite einschränken und jede linke Zeile erhalten | ON |
| Einschränken, welche linken Zeilen in den Bericht gehören | WHERE |
| Zeilen finden, deren rechter Partner fehlt | WHERE mit right_key IS NULL |
Die Anti-Join-Prüfung gehört hinter den Join, weil sie das mit NULL aufgefüllte Ergebnis untersucht. Inner Joins haben keine erhaltenen Zeilen ohne Partner. Daher ändert das Verschieben eines Filters zwischen ON und WHERE ihre passenden Paare nicht. Lies bei der Prüfung eines Outer Joins jeden WHERE-Test für die optionale Seite und prüfe, was er mit einer mit NULL aufgefüllten Zeile macht.
Wichtige Erkenntnisse
ONentscheidet über die Partner;WHEREfiltert fertige Ergebniszeilen.- Setze eine Einschränkung der rechten Seite in
ON, um linke Zeilen ohne passende Partner zu erhalten. - Setze Berichtseinschränkungen für die linke Seite in
WHERE. - Ein rechtsseitiger Vergleich in
WHEREentfernt mit NULL aufgefüllte Zeilen, wenn er unbekannt ist. - Die
IS NULL-Prüfung des Anti-Joins wird bewusst nach dem Join ausgeführt.
4Self Joins und Cross Joins
Dieselbe Join-Technik kann zwei Rollen in einer Tabelle verbinden oder alle Kombinationen zweier Tabellen bilden. Abfragen zu Mitarbeitern und Vorgesetzten brauchen Aliase, die die Rollen klar unterscheiden. Für Kollegenpaare ist außerdem eine Regel für Selbstpaarungen und umgekehrte Duplikate nötig. Cross Joins erzeugen bewusst alle Möglichkeiten, etwa Größen und Farben. Wenn du ihre Größe vorhersagst, erkennst du leichter, wann diese Vervielfachung beabsichtigt war und wann eine Bedingung fehlt.
4.1 Zwei Rollen für eine Tabelle
Der Vorgesetzte eines Mitarbeiters ist ebenfalls ein Mitarbeiter. Ein Self Join liest dieselbe Tabelle unter verschiedenen Aliasen, sodass eine Zeile den Mitarbeiter und eine andere den Vorgesetzten darstellen kann. Er verwendet die übliche Join-Syntax; ein Schlüsselwort SELF JOIN gibt es nicht.
Die Rollen vor den Spalten benennen
Die Mitarbeiterdaten lauten:
| emp_id | name | manager_id |
|---|---|---|
| 1 | Grace | NULL |
| 2 | Hassan | 1 |
| 3 | Iris | 1 |
| 4 | Jamal | 2 |
SELECT e.name AS employee, m.name AS manager
FROM employees e
JOIN employees m ON e.manager_id = m.emp_id;
e liefert die Mitarbeiterzeile. Ihre manager_id zeigt auf die emp_id des Vorgesetzten in der Rolle m. Hassan zeigt auf 1 und wird daher mit Grace gepaart; auch Iris wird mit Grace gepaart. Jamal zeigt auf 2 und wird mit Hassan gepaart. Das Ergebnis ist (Hassan, Grace), (Iris, Grace) und (Jamal, Hassan).
Grace hat keinen Vorgesetzten. Ihre manager_id ist NULL, daher schließt der Inner Join sie aus. Ersetzt du JOIN durch LEFT JOIN, kommt (Grace, NULL) hinzu und es entstehen vier Zeilen. Unterschiedliche Aliase ermöglichen es der Datenbank, die Rollen auseinanderzuhalten, obwohl beide Eingaben aus derselben gespeicherten Tabelle stammen.
Die Frage in der anderen Richtung stellen
Um Personen zu finden, die niemanden führen, beginne mit der Rolle des Vorgesetzten und suche nach einem fehlenden Mitarbeiter:
SELECT m.name
FROM employees m
LEFT JOIN employees e ON e.manager_id = m.emp_id
WHERE e.emp_id IS NULL;
Dies gibt (Iris) und (Jamal) zurück. Zu Grace passen Hassan und Iris; zu Hassan passt Jamal. Iris und Jamal haben keine direkt unterstellten Mitarbeiter. Die Prüfung des Mitarbeiterschlüssels nach dem Join findet ihren fehlenden Partner.
Ein dritter Alias folgt einer weiteren Ebene. employees e JOIN employees m ON e.manager_id = m.emp_id JOIN employees g ON m.manager_id = g.emp_id gibt bei Auswahl ihrer Namen (Jamal, Hassan, Grace) zurück. Jede zusätzliche Rolle folgt einer weiteren Verknüpfung. Eine feste Abfrage erreicht eine feste Anzahl von Ebenen; eine Hierarchie beliebiger Tiefe braucht eine rekursive Abfrage.
Kollegen einmal paaren
Dieselbe Tabelle kann auch Kollegenpaare liefern:
SELECT a.name, b.name
FROM employees a
JOIN employees b
ON a.manager_id = b.manager_id
AND a.emp_id < b.emp_id;
Hassan und Iris haben denselben Vorgesetzten mit der Kennung 1. Die Kleiner-als-Prüfung schließt aus, dass eine Person mit sich selbst gepaart wird, und erhält nur eine Reihenfolge jedes Paares. Das Ergebnis ist (Hassan, Iris).
Mit der Gleichheitsbedingung für den Vorgesetzten allein hat das Ergebnis fünf Zeilen: Hassan–Hassan, Hassan–Iris, Iris–Hassan, Iris–Iris und Jamal–Jamal. Graces NULL-Vorgesetztenschlüssel passt zu nichts, auch nicht zu einem anderen NULL. Ersetzt du < durch <>, werden Selbstpaarungen ausgeschlossen, aber sowohl (Hassan, Iris) als auch (Iris, Hassan) erhalten. Wähle <, wenn die Frage jedes ungeordnete Paar einmal verlangt.
Wichtige Erkenntnisse
- Verwende für die unterschiedlichen Rollen in einem Self Join verschiedene Aliase.
- Gleiche die
manager_ideines Mitarbeiters mit deremp_idder Vorgesetztenrolle ab. - Ein Left Self Join kann die oberste Person einer Hierarchie erhalten.
- Jeder zusätzliche Self Join folgt einer weiteren festen Ebene.
- Bei Paaren derselben Gruppe entfernt
<Selbstpaarungen und umgekehrte Duplikate;<>entfernt nur Selbstpaarungen.
4.2 Jede mögliche Kombination
Ein Cross Join bildet ohne Abgleichsbedingung jedes Zeilenpaar. Das ist nützlich, wenn die Frage nach Möglichkeiten fragt, etwa nach jeder Kombination aus Größe und Farbe, die ein Geschäft vorrätig halten könnte.
Die Kombinationsliste erstellen
sizes enthält S, M und L. colors enthält Red und Blue.
SELECT s.size, c.color
FROM sizes s
CROSS JOIN colors c;
Die sechs Paare sind (S, Red), (S, Blue), (M, Red), (M, Blue), (L, Red) und (L, Blue). Jede Größe erscheint neben beiden Farben. Das sind die Ergebniszeilen; ihre Anzeigereihenfolge ist ohne ORDER BY nicht garantiert.
Bei zwei Eingaben multiplizierst du ihre Zeilenanzahlen. Drei Größen und zwei Farben ergeben sechs Zeilen. Kommt eine dritte Tabelle mit vier Optionen hinzu, hat das Ergebnis 24 Zeilen. Ist eine Eingabe leer, lässt sich keine vollständige Kombination bilden und das Ergebnis hat null Zeilen.
Mit einem vollständigen Berichtsraster beginnen
Verkaufsdatensätze zeigen nur Kombinationen, die aufgetreten sind. Um jedes Geschäft in jedem Monat anzuzeigen, bilde zunächst mit stores CROSS JOIN months ein Raster. Füge dann mit einem Left Join passende Verkaufsdatensätze hinzu:
SELECT s.store_id, m.month, x.total
FROM stores s
CROSS JOIN months m
LEFT JOIN sales x
ON x.store_id = s.store_id
AND x.month = m.month;
Das Raster erhält ein Geschäfts-Monats-Paar auch dann, wenn es keinen Verkauf gibt; in x.total steht dann NULL. Beide Schlüsselteile sind wichtig: Ein Abgleich nur über das Geschäft würde auch dessen Verkäufe aus anderen Monaten hinzufügen. Der Cross Join bestimmt, welche Kombinationen der Bericht zeigen muss, und der Left Join liefert die dazu verfügbaren Fakten.
Einen unbeabsichtigten Cross Join erkennen
FROM customers, orders ohne Verknüpfungsbedingung bildet aus den vier Kunden und vier Bestellungen 16 Paare. Ana wird mit ihren eigenen Bestellungen, Bens Bestellung und der Gastbestellung gepaart. Bei jedem Kunden geschieht dasselbe. Das ist nur sinnvoll, wenn tatsächlich jede Kunden-Bestellungs-Kombination gewünscht ist.
Eine hohe Zeilenanzahl ist ein Hinweis, aber prüfe auch die Paarungen. Bei 1.000 Kunden und 1.000 Produkten erzeugt ein beabsichtigter Cross Join 1.000.000 Zeilen. Ein Join mit einer falschen, aber einschränkenden Bedingung kann auch ein kleineres, falsches Ergebnis zurückgeben. Vergleiche die Anzahl und die Bedeutung jedes Paares mit der Frage.
Gleichwertige Formen erkennen
CROSS JOIN, ein Komma-Join ohne Abgleichsbedingung und ein Inner Join mit ON 1 = 1 erhalten alle jedes Paar. SQLite und MySQL akzeptieren auch ein einfaches JOIN ohne ON und behandeln es als Cross Join; PostgreSQL verlangt für einen einfachen Join ON oder USING. Schreibe CROSS JOIN, wenn jede Kombination beabsichtigt ist.
DISTINCT entfernt identische ausgewählte Zeilen, keine falschen Beziehungen. Paart ein unbeabsichtigter Cross Join Ana mit Bens Bestellung, bleiben diese Werte eine eigenständige Zeile. Ergänze die fehlende Bedingung, statt einen Teil der wiederholten Ausgabe zu verbergen.
Wichtige Erkenntnisse
- Ein Cross Join gibt jede Kombination zurück; multipliziere die Zeilenanzahlen der Eingaben.
- Eine leere Eingabe macht das kartesische Produkt leer.
- Ein Cross Join kann ein vollständiges Raster für einen späteren Left Join erstellen.
- Eine fehlende Abgleichsbedingung kann einen unbeabsichtigten Cross Join erzeugen.
DISTINCTentfernt keine falschen Paarungen.
5Zwischentabellen und längere Pfade
Manche Berichte brauchen einen Weg durch mehrere Tabellen, bevor sich die angefragten Fakten zusammenführen lassen. Einschreibungszeilen verbinden Studierende mit Kursen, und Bestellpositionen verbinden Bestellungen mit Produkten. Folge jeweils einem Schlüssel, behalte im Blick, wofür jede Ergebniszeile steht, und wähle, welche Verknüpfungen erforderlich sind. Ein Left Join am Anfang einer Kette kann seine Zeilen ohne Partner bei einem späteren Schritt verlieren. Deshalb muss der gesamte Pfad die für den Bericht vorgesehenen Datensätze erhalten.
5.1 Einer Viele-zu-viele-Verknüpfung folgen
Ein Studierender kann mehrere Kurse belegen, und ein Kurs kann mehrere Studierende haben. Eine Zwischentabelle erfasst diese Viele-zu-viele-Verknüpfungen als einzelne Paare. Sie wird auch Brückentabelle, Verknüpfungstabelle oder assoziative Tabelle genannt.
Eine Verknüpfung pro Zeile lesen
Die Beispieldaten enthalten die Studierenden 1 Mia, 2 Noah und 3 Omar; die Kurse 10 Algebra, 20 Biology und 30 Chemistry; sowie die Einschreibungspaare (1, 10), (1, 20) und (2, 10).
| student_id | course_id |
|---|---|
| 1 | 10 |
| 1 | 20 |
| 2 | 10 |
Studierender 1 erscheint zweimal, weil Mia zwei Kurse belegt. Kurs 10 erscheint zweimal, weil Algebra zwei Studierende hat. Keine der Spalten muss für sich genommen eindeutig sein. Das Paar kann einen zusammengesetzten Primärschlüssel bilden, PRIMARY KEY (student_id, course_id), der verhindert, dass derselbe Studierende zweimal in denselben Kurs eingeschrieben wird.
Eine Verknüpfung kann eigene Fakten haben. enrolled_on gehört zur Einschreibung, weil es beschreibt, wann ein bestimmter Studierender einem bestimmten Kurs beigetreten ist. Ebenso beschreibt order_items.quantity, wie viel von einem bestimmten Produkt zu einer bestimmten Bestellung gehört.
Die Zwischentabelle mit zwei Joins durchlaufen
SELECT s.name, c.title
FROM students s
JOIN enrollments e ON e.student_id = s.student_id
JOIN courses c ON c.course_id = e.course_id;
Die erste Bedingung fügt die Einschreibungszeilen jedes Studierenden hinzu. Die zweite ersetzt den Kursverweis jeder Einschreibung durch Fakten aus der Kurstabelle. Das vollständige Ergebnis ist (Mia, Algebra), (Mia, Biology) und (Noah, Algebra). Jede Zeile steht für eine Einschreibung.
Keine der beiden Tabellen an den Enden enthält einen Schlüssel vom Studierenden zum Kurs. Ein Abgleich mit s.student_id = c.course_id würde nicht zusammengehörige Kennungen vergleichen und die Einschreibungsdaten überspringen. Die Zwischentabelle liefert die Beziehung.
Derselbe Pfad funktioniert in beide Richtungen. Ergänze WHERE c.title = 'Algebra', um (Mia, Algebra) und (Noah, Algebra) zu erhalten. Ergänze stattdessen WHERE s.name = 'Mia', um (Mia, Algebra) und (Mia, Biology) zu erhalten. Die Verknüpfungen bleiben gleich; der Filter wählt aus, welche davon die Frage beantworten.
Personen oder Kurse ohne Verknüpfungen einbeziehen
Beginne bei der Seite, die erhalten bleiben muss. students s LEFT JOIN enrollments e ON e.student_id = s.student_id erhält Omar mit NULL in den Einschreibungsspalten. Um Kurstitel anzuzeigen und ihn dabei zu erhalten, muss auch der spätere Join von enrollments zu courses die fehlende Einschreibung erhalten.
Um Kurse zu finden, die niemand belegt, verwende die Kursseite und einen Anti-Join:
SELECT c.title
FROM courses c
LEFT JOIN enrollments e ON e.course_id = c.course_id
WHERE e.student_id IS NULL;
Dies gibt (Chemistry) zurück. Bei einer tatsächlich passenden Einschreibung ist student_id Teil des Primärschlüssels und kann nicht NULL sein. Die Prüfung erkennt daher die fehlende Verknüpfung.
Speichere eine Beziehung pro Zeile der Zwischentabelle. Eine Textliste wie „10,20“ in einem Studierendenfeld kann durch einen Gleichheitsvergleich nicht mit den einzelnen Kurs-IDs 10 und 20 abgeglichen werden. Getrennte Paare ermöglichen es jeder Join-Bedingung, einen Verweis mit einem Schlüssel zu vergleichen.
Wichtige Erkenntnisse
- Eine Zeile der Zwischentabelle erfasst ein Paar und kann Fakten über diese Beziehung enthalten.
- Die beiden Fremdschlüssel können einen zusammengesetzten Schlüssel bilden, der doppelte Paare verhindert.
- Zwei Joins verbinden die Tabellen an den Enden über die Zwischentabelle.
- Beginne beim Endpunkt, der erhalten bleiben muss, wenn du fehlende Beziehungen suchst.
5.2 Ein Pfad über vier Tabellen
Für einen längeren Join gilt dieselbe Regel wie für einen Join aus zwei Tabellen: Füge die nächste Tabelle mit einer sinnvollen Bedingung hinzu. Verfolge vor dem Schreiben der Abfrage die Schlüssel und entscheide, was eine Ergebniszeile darstellen soll.
Die detaillierten Ladendaten hinzufügen
| product_id | name | price |
|---|---|---|
| 1 | Mug | 8,00 |
| 2 | Pen | 1,50 |
| 3 | Notebook | 4,25 |
| 4 | Stapler | 12,00 |
Die Bestellpositionen (order_id, product_id, quantity) sind (101, 1, 2), (101, 2, 4), (102, 3, 6), (103, 1, 6), (103, 2, 8) und (104, 2, 10). Jede Position verbindet eine Bestellung mit einem Produkt und erfasst eine Menge.
Für die Frage „Was hat jeder Kunde gekauft?“ folge customers → orders → order_items → products. Die Schlüssel entlang des Pfads sind Kunden-ID, Bestell-ID und Produkt-ID. Vier Tabellen entlang dieser Kette brauchen drei Verknüpfungen.
Jeweils eine neue Tabelle hinzufügen
SELECT c.name, o.order_id, p.name AS product,
oi.quantity, oi.quantity * p.price AS line_total
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id
JOIN order_items oi ON oi.order_id = o.order_id
JOIN products p ON p.product_id = oi.product_id
ORDER BY o.order_id, p.product_id;
Jedes ON verweist auf die neu eingeführte Tabelle und eine bereits verfügbare. Produkte werden über Bestellpositionen hinzugefügt, nicht direkt über Kunden. Das Ergebnis lautet:
| name | order_id | product | quantity | line_total |
|---|---|---|---|---|
| Ana | 101 | Mug | 2 | 16,00 |
| Ana | 101 | Pen | 4 | 6,00 |
| Ana | 102 | Notebook | 6 | 25,50 |
| Ben | 103 | Mug | 6 | 48,00 |
| Ben | 103 | Pen | 8 | 12,00 |
Der erste Join schließt Gastbestellung 104 aus, weil ihr Kundenverweis NULL ist. Die verbleibenden drei Bestellungen enthalten fünf Positionen, daher hat das Endergebnis fünf Zeilen. Bei Bestellung 101 kosten zwei Tassen 16,00 und vier Stifte 6,00, passend zur Bestellsumme von 22,00.
Wissen, was eine Zeile zählt
Eine Ergebniszeile steht für eine Bestellposition. Ana und Bestellung 101 erscheinen zweimal, weil diese Bestellung zwei Produkte hat. Wiederholte Kundennamen sind daher zu erwarten. Werden diese Zeilen gezählt, zählt man Positionen, keine unterschiedlichen Kunden oder Bestellungen.
Ein Filter kann auf jede verknüpfte Tabelle verweisen. Ergänzt du vor ORDER BY ein WHERE p.name = 'Pen', bleiben (Ana; 101; Pen; 4; 6,00) und (Ben; 103; Pen; 8; 12,00) erhalten. Kein Produktfilter kann die Gastbestellung zurückholen, die bereits bei der Kundenverknüpfung ausgeschlossen wurde.
Jede Verknüpfung sichtbar halten
Bei einer Kette von Inner Joins kann sich die Reihenfolge der Tabellen ändern, ohne die passenden Kombinationen zu verändern, sofern jede Bedingung nur auf bereits eingeführte Tabellen verweist. Am leichtesten zu lesen ist es meist, beim Gegenstand des Berichts zu beginnen und dessen Schlüsseln zu folgen.
Eine fehlende Bedingung kann in SQLite oder MySQL ein Zwischenergebnis vervielfachen, da diese ein einfaches JOIN ohne ON akzeptieren. PostgreSQL und SQL Server lehnen diese Syntax ab. Eine fehlende Bedingung in einer Abfrage mit Kommaschreibweise kann bei diesem Schritt ebenfalls jede Kombination erzeugen.
Manchmal erfüllt eine Tabelle zwei Rollen. Ein Flugbericht kann airports als dep über dep.code = f.from_code und erneut als arr über arr.code = f.to_code verknüpfen. Unterschiedliche Aliase geben den Abflug- und Ankunftsdaten getrennte Plätze im Ergebnis.
Wichtige Erkenntnisse
- Ergänze eine Join-Bedingung für jede Verknüpfung im Tabellenpfad.
- Jedes
ONdarf die neue Tabelle und bereits eingeführte Tabellen verwenden. - Bestimme, wofür eine Ergebniszeile steht, bevor du Werte zählst oder addierst.
- Eine Tabelle kann unter verschiedenen Aliasen erscheinen, wenn der Bericht unterschiedliche Rollen braucht.
5.3 Optionale Zeilen über eine Kette hinweg erhalten
Ein Left Join erhält Zeilen bei einem Schritt. Spätere Joins und Filter wirken weiterhin auf das Ergebnis dieses Schritts. Um eine Elternzeile ohne Partner über einen längeren Pfad zu erhalten, verfolge bei jedem Schritt, was mit ihren mit NULL aufgefüllten Spalten geschieht.
Sehen, wo eine erhaltene Zeile verschwindet
SELECT c.name, o.order_id, oi.product_id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
JOIN order_items oi ON oi.order_id = o.order_id;
Der erste Schritt bildet fünf Zeilen: Anas zwei Bestellungen, Bens Bestellung und je eine mit NULL aufgefüllte Zeile für Chloe und Dev. Beim nächsten Schritt sind die o.order_id-Werte von Chloe und Dev NULL. Sie können die Gleichheitsbedingung mit einem Bestellpositionsschlüssel nicht erfüllen, sodass der Inner Join sie entfernt. Die Abfrage gibt fünf Bestellpositionszeilen zurück und verliert beide Kunden ohne Bestellungen.
Den optionalen Pfad erhalten
SELECT c.name, o.order_id, oi.product_id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
LEFT JOIN order_items oi ON oi.order_id = o.order_id;
Nun erhält auch der zweite Join diese mit NULL aufgefüllten Zeilen. Das Ergebnis enthält (Ana, 101, 1), (Ana, 101, 2), (Ana, 102, 3), (Ben, 103, 1), (Ben, 103, 2), (Chloe, NULL, NULL) und (Dev, NULL, NULL): sieben Zeilen.
Wenn spätere Joins von Spalten einer optionalen Tabelle abhängen, müssen sie gewöhnlich Left Joins bleiben, um fehlende Partner zu erhalten. Ein späterer Inner Join über Spalten einer erforderlichen Tabelle hat eine andere Rolle. Untersuche daher die tatsächliche Abhängigkeit in jeder Bedingung.
Derselben Regel durch eine Zwischentabelle folgen
SELECT s.name, c.title
FROM students s
LEFT JOIN enrollments e ON e.student_id = s.student_id
LEFT JOIN courses c ON c.course_id = e.course_id;
Dies gibt (Mia, Algebra), (Mia, Biology), (Noah, Algebra) und (Omar, NULL) zurück. Wird der letzte Join zu einem Inner Join, entfernt er Omar, weil seine fehlende Einschreibung zu keinem Kurs passen kann.
Klammern bieten eine weitere Möglichkeit, die Gruppierung auszudrücken: students s LEFT JOIN (enrollments e JOIN courses c ON c.course_id = e.course_id) ON e.student_id = s.student_id. Die passenden Einschreibungs-Kurs-Paare bilden die optionale Gruppe; der Outer Join fügt diese Gruppe jedem Studierenden hinzu und erhält Omar.
Spätere Filter und die Join-Richtung prüfen
Ergänzt du die Studierendenabfrage, die nur Left Joins enthält, um WHERE c.title = 'Algebra', bleiben nur Mia und Noah in Algebra. Der Vergleich ist für Omars NULL-Kurstitel unbekannt. Das beantwortet „Wer belegt Algebra?“, aber nicht mehr „Zeige alle Studierenden und ihre Kurse“. Eine IS NULL-Prüfung verhält sich anders, weil sie einen fehlenden Wert bewusst akzeptiert.
Ein späterer Right Join ändert die erhaltene Seite erneut: Er erhält die neu hinzugefügte rechte Tabelle, und frühere Zeilen ohne Partner können verschwinden. Stelle die Tabelle, die erhalten bleiben muss, an den Anfang und füge optionale Pfade mit Left Joins hinzu, wenn dies den Bericht klar ausdrückt.
Baue die Abfrage Join für Join auf und prüfe sie nach jedem Schritt. Notiere sowohl die Zeilenanzahl als auch die verbleibenden Schlüssel. Eine sinkende Anzahl kann verlorene Zeilen ohne Partner aufdecken; ein unerwarteter Anstieg kann auf einen fehlenden Schlüsselteil hinweisen. Manche Anzahlen bleiben unverändert, wenn Zeilen sowohl verloren gehen als auch vervielfacht werden. Prüfe deshalb auch repräsentative Schlüssel.
Wichtige Erkenntnisse
- Jeder Join wirkt auf das bisher aufgebaute Ergebnis.
- Ein Inner Join über den NULL-Schlüssel einer optionalen Tabelle entfernt Zeilen ohne Partner.
- Halte spätere abhängige Verknüpfungen optional, wenn ihre fehlenden Zeilen erhalten bleiben müssen.
- Ein späterer
WHERE-Vergleich kann weiterhin Zeilen entfernen, die durch Left Joins erhalten wurden. - Prüfe nach jedem Schritt die Anzahl und die erhaltenen Schlüssel.
6Zuverlässige Anzahlen und Ergebnisse
Wiederholte Werte sind oft eine korrekte Folge eines Joins, können aber die Anzahlen und Summen eines Berichts verfälschen. Verfolge eine Bestellsumme, die durch Detailzeilen wiederholt wird, wähle die richtige Kennung zum Zählen und unterscheide ein nützliches DISTINCT von einem verborgenen Join-Fehler. Prüfe einen Bericht dann anhand der vorhergesagten Treffer, vollständiger Schlüssel, des NULL-Verhaltens und einheitlicher Schlüsselformate, bevor du seiner plausibel aussehenden Ausgabe vertraust.
6.1 Auf der richtigen Ebene zählen und addieren
Ein Join kann korrekt sein, während ein Aggregat über seinem Ergebnis falsch ist. Die entscheidende Frage ist, was eine Zeile nach dem Join darstellt. Ein Wert, der einmal pro Bestellung gespeichert ist, kann in einer Liste von Bestellpositionen mehrfach erscheinen.
Eine wiederholte Bestellsumme verfolgen
Ana hat Bestellung 101 über 22,00 und Bestellung 102 über 25,50. Die Summe der beiden Bestellungen beträgt 47,50. Bestellung 101 hat zwei Positionen, daher wiederholt der Join mit order_items die 22,00 zweimal; Bestellung 102 hat eine Position. Addiert man die wiederholten Werte, ergibt sich 69,50.
SELECT c.customer_id, c.name, SUM(o.total) AS spent
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id
GROUP BY c.customer_id, c.name;
GROUP BY fasst die Zeilen jedes Kunden zusammen und SUM addiert die Werte dieser Gruppe. Diese Abfrage gibt (1; Ana; 47,50) und (2; Ben; 60,00) zurück. Ein zusätzlicher Join mit den Bestellpositionen vor der Gruppierung würde Anas Summe auf 69,50 und Bens Summe auf 120,00 erhöhen. Die Summen der beiden Kunden würden zusammen 189,50 statt 107,50 betragen.
Über alle vier Bestellungen einschließlich der Gastbestellung 104 führt ein direkter Join der Bestellungen mit ihren Positionen dazu, dass SUM(o.total) 204,50 statt 122,50 zurückgibt. Dieser Fan-out entsteht durch die Eins-zu-viele-Verknüpfung, nicht durch einen Syntaxfehler.
Fakten auf ihrer gespeicherten Ebene summieren
Summiere für Bestellsummen die Bestellungen, ohne die Detailtabelle hinzuzufügen. Berechne für eine Summe der Positionsbeträge den Wert jeder einzelnen Position:
SELECT SUM(oi.quantity * p.price) AS sales
FROM order_items oi
JOIN products p ON p.product_id = oi.product_id;
Die sechs Positionsbeträge sind 16,00, 6,00, 25,50, 48,00, 12,00 und 15,00. Zusammen ergeben sie 122,50, die Summe aller vier Bestellungen. Jedes Produkt aus Menge und Preis gehört zu einer Position und wird daher einmal addiert.
Tatsächliche Treffer zählen
Nach dem Join von Kunden mit Bestellungen und Positionen belegt Ana drei Zeilen. COUNT(*) zählt diese Positionen; COUNT(DISTINCT o.order_id) zählt ihre zwei unterschiedlichen Bestellungen.
Nach einem einfachen Left Join von Kunden zu Bestellungen zählt COUNT(*) eine mit NULL aufgefüllte Zeile für Chloe und eine für Dev. Zähle stattdessen den optionalen Bestellschlüssel:
SELECT c.customer_id, c.name, COUNT(o.order_id) AS orders
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
GROUP BY c.customer_id, c.name;
Dies gibt (1, Ana, 2), (2, Ben, 1), (3, Chloe, 0) und (4, Dev, 0) zurück. COUNT(column) ignoriert NULL-Werte; COUNT(*) zählt Zeilen.
Zwei Viele-Seiten multiplizieren sich gegenseitig
Hat ein Kunde drei Bestellungen und zwei Supportanfragen, erzeugt ein unabhängiger Join beider Kindtabellen mit diesem Kunden sechs Zeilen. Jede Bestellung wird mit jeder Anfrage gepaart. Einfache Zählungen eines der beiden Kindschlüssel ergeben jeweils sechs. Zähle unterschiedliche Kindschlüssel, um drei und zwei zu erhalten, oder fasse die Kindtabellen getrennt zusammen.
DISTINCT c.customer_id, c.name ist für eine eindeutige Kundenliste nützlich. Der Schlüssel verhindert, dass verschiedene Kunden mit demselben Namen zusammengefasst werden. Er behebt keine fehlende Join-Bedingung. Auch SUM(DISTINCT o.total) ist unsicher: Es fasst zwei getrennte Bestellungen zusammen, die zufällig denselben Betrag haben.
Wichtige Erkenntnisse
- Eins-zu-viele-Joins wiederholen Elternwerte; summiere einen Wert auf der Ebene, auf der er gespeichert ist.
COUNT(*)zählt Zeilen;COUNT(column)überspringt NULL-Werte.COUNT(DISTINCT key)zählt nach einem Fan-out unterschiedliche Kennungen, die nicht NULL sind.- Zwei unabhängige Joins auf der Viele-Seite können sich gegenseitig vervielfachen.
SUM(DISTINCT amount)kann verschiedene Datensätze mit gleichen Beträgen zusammenfassen.- Behalte in einer Liste eindeutiger Entitäten einen identifizierenden Schlüssel.
6.2 Treffer prüfen, bevor du einem Bericht vertraust
Eine Abfrage kann laufen und trotzdem die falschen Beziehungen beschreiben. Sage vor der Verwendung eines Join-Ergebnisses voraus, was erhalten bleiben sollte, wie oft jeder Schlüssel erscheinen sollte und was eine Ergebniszeile bedeuten sollte.
Die Zeilenanzahl vorhersagen
Wenn der Kundenverweis einer Bestellung zu einem eindeutigen Kundenschlüssel passt, hat jede Bestellung höchstens einen Kunden als Partner. Ein Inner Join gibt daher höchstens eine Zeile pro Bestellung zurück. In den Ladendaten haben drei von vier Bestellungen einen Kunden, also gibt der Inner Join zwischen Kunden und Bestellungen drei Zeilen zurück.
Von der Kundenseite aus gibt ein Left Join die drei passenden Paare sowie je eine Zeile für Chloe und Dev zurück: fünf Zeilen. Ein Cross Join der vier Kunden und vier Bestellungen ergibt 16. Diese Vorhersagen bieten unterschiedliche Prüfungen für unterschiedliche Join-Typen; die Anzahl der Tabellen allein bestimmt die Zeilenanzahl nicht.
Die Struktur eines falschen Ergebnisses untersuchen
| Anzeichen | Was du prüfen solltest |
|---|---|
| Jede linke Zeile wird mit jeder rechten Zeile gepaart | Fehlende oder immer wahre Bedingung |
| Keine Treffer oder Paarungen nicht zusammengehöriger Entitäten | Falsche Spalten oder nicht kompatible Schlüsselwerte |
| Ein logischer Datensatz hat mehrere Partner | Ein unvollständiger Schlüssel, ein doppelter Nachschlageschlüssel oder eine erwartete Eins-zu-viele-Verknüpfung |
| Elternzeilen ohne Kindzeilen verschwinden | Ein Inner Join oder ein Filter für die optionale Seite an späterer Stelle der Abfrage |
Ein Abgleich nur über store_id, wenn Datensätze durch (store_id, month) identifiziert werden, vermischt verschiedene Monate. Gleiche jeden Bestandteil mit AND ab. Eine Abfrage, die zufällig funktioniert, solange für ein Geschäft ein Monat vorhanden ist, kann fehlschlagen, sobald ein zweiter Monat geladen wird.
Fehlende Werte von falschen Schlüsseln unterscheiden
Bei gewöhnlicher Gleichheit passen NULL-Schlüssel nicht zusammen, auch nicht NULL mit NULL. Ein Join von Bestellungen mit sich selbst über customer_id ergibt vier Paare aus Anas zwei Bestellungen und eines aus Bens Bestellung, also fünf Zeilen. Die Gastbestellung trägt keines bei. Ein Outer Join ist nötig, wenn eine Zeile mit fehlendem Verweis erhalten bleiben muss.
Doppelte Nachschlagewerte vervielfachen nur die Treffer für diese Werte. Kommt ein Ländercode zweimal in einer Nachschlagetabelle vor, erhält jeder Kunde mit diesem Code zwei Partnerzeilen. Codes, die einmal vorkommen, ergeben weiterhin einen Partner. Prüfe eine Nachschlagetabelle, deren Werte eindeutig sein sollten, mit:
SELECT code, COUNT(*) AS copies
FROM countries
GROUP BY code
HAVING COUNT(*) > 1;
GROUP BY fasst die Zeilen jedes Codes zusammen; HAVING erhält Gruppen, deren Anzahl größer als eins ist. Würde die gesamte Nachschlagetabelle zweimal geladen, verdoppelten sich die Zeilen jedes passenden Kunden.
Prüfe auch Schlüsseltypen und -formate. Der Text „0042“ und die Zahl 42 können je nach Datenbank zu unterschiedlichem Verhalten führen: kein Treffer, ein Typfehler oder eine automatische Umwandlung. SQLite kann eine TEXT-Spalte mit „0042“ mit einer INTEGER-Spalte mit 42 abgleichen. Verwende einheitliche Schlüsseltypen und -formate oder eine ausdrückliche Umwandlung, die zur beabsichtigten Bedeutung passt.
Die Anforderungen des Berichts durchgehen
Frag dich, welche Tabelle alle Zeilen behalten muss. Verfolge ihren vollständigen Schlüsselpfad und prüfe jede Bedingung anhand des Schemas. Entscheide, warum jede Verknüpfung ein Inner oder Outer Join ist, und prüfe dann, ob jeder Filter beim Abgleich oder danach wirken soll. Vergleiche die Zeilenanzahlen nach jedem Schritt und untersuche eine bekannte Zeile mit einem Partner, eine Zeile ohne Partner und eine Zeile mit mehreren Partnern. Prüfe schließlich, ob jede Anzahl und Summe die beabsichtigte Art von Datensatz misst.
Wichtige Erkenntnisse
- Sage Anzahlen anhand der Beziehung und des Join-Typs voraus.
- Prüfe jeden Bestandteil eines zusammengesetzten Schlüssels.
- Gewöhnliche Gleichheit behandelt NULL-Schlüssel nie als passend.
- Doppelte Nachschlageschlüssel vervielfachen die betroffenen Treffer.
- Halte Typen und Formate verknüpfter Schlüssel einheitlich.
- Prüfe erhaltene Kennungen ebenso wie Summen und Zeilenanzahlen.
SQL-Joins: Beispiele
1Von Schemaverknüpfungen zu verknüpften Zeilen
10 Schritte
- 1EinführungMit der Frage des Berichts beginnen
Ein Bericht braucht Kundennamen neben Bestellsummen, aber diese Fakten stehen in verschiedenen Tabellen. Ein Join führt die zusammengehörigen Zeilen zusammen.
Finde zuerst die Schlüsselverknüpfung. Stelle dir dann die Paare vor, die sie zulässt. Diese Reihenfolge hilft dir, das Ergebnis vor dem Schreiben von SQL vorherzusagen: Ein Name kann sich wiederholen, weil es mehrere passende Bestellungen gibt, und eine Zeile kann verschwinden, weil sie keinen Partner hat.
- 2BeispielKunden- und Bestellschlüssel lesen
Die Kunden sind 1 Ana, 2 Ben, 3 Chloe und 4 Dev. Die Bestellungen 101 und 102 verweisen auf Kunde 1; Bestellung 103 verweist auf Kunde 2. Bestellung 104 ist eine Gastbestellung mit einem Kundenverweis NULL.
Die Verknüpfung lautet
orders.customer_id→customers.customer_id. Die Bestellnummer identifiziert einen Kauf, während der Kundenverweis den zugehörigen Kunden identifiziert. Ein Vergleich dieser beiden unterschiedlichen Arten von IDs würde die Zugehörigkeit nicht ausdrücken. - 3ErklärungDen Verweis auf die Viele-Seite setzen
Ein Kunde kann mehrere Bestellungen aufgeben. Jede Bestellung speichert einen Kundenverweis, daher ist
ordersdie Viele-Seite der Verknüpfung.Bei einer Eins-zu-eins-Verknüpfung ist dieser Verweis außerdem eindeutig. Bei Viele-zu-viele-Verknüpfungen, etwa wenn Studierende Kurse belegen, erfasst eine Zwischentabelle die Paare. Diese Strukturen zeigen dir, welchem Pfad ein Bericht folgen muss und wo mehrere Partner möglich sind.
- 4HerausforderungDen fehlenden Pfad finden
Du brauchst die Produkte, die jeder Kunde gekauft hat. Das Schema verbindet customers mit orders, orders mit order_items und order_items mit products. Kannst du order_items überspringen und die Bestell-ID direkt mit der Produkt-ID vergleichen?
---reveal---
Nein. Diese IDs identifizieren unterschiedliche Dinge. Folge customers → orders → order_items → products. Jede order_items-Zeile erfasst ein Produkt in einer bestimmten Bestellung und liefert damit die Verknüpfung, die dem direkten Vergleich fehlt.
- 5BeispielDie ersten Paare bilden
Wende
o.customer_id = c.customer_idan. Bestellung 101 passt zu Ana, weil beide Kundenwerte 1 sind. Bestellung 102 bildet ein weiteres Paar mit Ana und Bestellung 103 passt zu Ben.Die Ergebnispaarungen sind (Ana, 101), (Ana, 102) und (Ben, 103). Chloe und Dev haben keine Partner. Gastbestellung 104 hat einen Kundenschlüssel NULL, daher ist ihre Gleichheitsbedingung unbekannt und liefert keinen Treffer.
- 6KernaussageEine Linie für jeden Treffer
Stelle dir eine Linie zwischen jeder Kundenzeile und jeder dazu passenden Bestellzeile vor. Jede Linie wird zu einer Ergebniszeile. Ana hat zwei Linien, daher erscheint ihr Name zweimal.
Dieses Bild funktioniert auch, wenn sich Schlüssel auf beiden Seiten wiederholen: Zwei linke und drei rechte Zeilen mit einem Schlüssel erzeugen sechs Linien. Überlappende Kreise können diese einzelnen Paarungen nicht zeigen oder erklären, wie ein Join länger als jede der Eingaben wird.
- 7TippDie Herkunft einer Spalte angeben
Gib den Tabellenverweisen Aliase, etwa
customers cundorders o. Schreibec.namefür den Kundennamen undo.totalfür die Bestellsumme.Beide Eingaben haben
customer_id. BeiJOIN ... ONist die Auswahl dieses Namens allein mehrdeutig; qualifiziere ihn alsc.customer_idodero.customer_id.SELECT *enthält alle sieben Eingabespalten, einschließlich beider Exemplare des Schlüssels. Wählst du nur benötigte Spalten aus, wird der Bericht schmaler. - 8ErklärungDer Abgleich kommt vor dem Filtern
Lies die logische Reihenfolge als Joins, dann
WHERE, dannSELECTund dannORDER BY. Ein Filter kann eine verknüpfte Spalte verwenden, die der Bericht nicht anzeigt.Filterst du beispielsweise die Kunden-Bestellungs-Paare mit
c.city = 'Denver', bleiben Anas zwei Bestellungen erhalten. Chloe wohnt auch in Denver, aber ein Inner Join hat für sie keine Zeile erzeugt. Ein späterer Filter kann eine beim Abgleich ausgeschlossene Zeile nicht zurückholen. - 9HerausforderungEin Ergebnis mit wiederholtem Schlüssel vorhersagen
Eine Tabelle mit Anmeldungen hat zwei Zeilen mit dem Standortschlüssel 8. Eine Standort-Nachschlagetabelle hat versehentlich drei Zeilen mit dem Schlüssel 8. Alle anderen Schlüssel fehlen. Wie viele Zeilen gibt ihr Inner Join mit Gleichheitsbedingung zurück, und ändert die Auswahl nur des Schlüssels diese Anzahl?
---reveal---
Es werden sechs Zeilen zurückgegeben: Jede Anmeldung passt zu allen drei Nachschlagezeilen. Die Auswahl nur des Schlüssels macht jede Zeile schmaler, erhält aber sechs Zeilen, sofern nicht eine separate Operation wie DISTINCT wiederholte ausgewählte Werte entfernt.
- 10ZusammenfassungErst die Beziehung, dann die Zeilen lesen
Finde den Schlüsselpfad, bevor du die Ergebnisspalten auswählst. Eins-zu-viele-Verknüpfungen können Elternwerte wiederholen; eine Zwischentabelle bildet eine Viele-zu-viele-Verknüpfung ab.
Frag dich für jedes Paar, ob die Bedingung wahr ist. Prüfe dann, wie viele Partner jede Zeile hat. Verwende Aliase, um die Herkunft der Spalten zu unterscheiden, und halte beim Erklären des Ergebnisses den Abgleich vom späteren Filtern und Sortieren getrennt.
2Inner Joins erstellen und lesen
11 Schritte
Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.
- 1EinführungAuf beiden Seiten einen Partner verlangen
- 2BeispielDie Schlüsselbedingung schreiben
- 3BeispielAlle drei Ergebniszeilen lesen
- 4HerausforderungEinen Kundenfilter hinzufügen
- 5TippDie vollständige Kennung abgleichen
- 6ErklärungEine Kurzform für gleiche Namen verwenden
- 7HerausforderungBeachten, was NATURAL verändert
- 8VerbindungEinen älteren Komma-Join lesen
- 9BeispielPreise Preisbereichen zuordnen
- 10HerausforderungEine Überlappung und eine Lücke beurteilen
- 11ZusammenfassungDie Bedingung hinter der Syntax lesen
3Zeilen ohne Partner erhalten, ohne sie durch Filter zu verlieren
14 Schritte
Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.
- 1EinführungEntscheiden, welche Datensätze bleiben müssen
- 2BeispielJeden Kunden erhalten
- 3HerausforderungDie zu erhaltende Seite ändern
- 4TippDen Schlüssel des fehlenden Partners prüfen
- 5ErklärungEinen Right Join als umgekehrten Left Join lesen
- 6BeispielDatensätze ohne Partner von beiden Seiten erhalten
- 7HerausforderungZwei neue Schlüssellisten abgleichen
- 8TippDie Unterstützung für Outer Joins prüfen
- 9BeispielPassende Bestellungen in ON einschränken
- 10BeispielDie Datumsprüfung nach WHERE verschieben
- 11HerausforderungDie linke Tabelle gezielt filtern
- 12VerbindungEntscheiden, was eine angezeigte Null bedeutet
- 13HerausforderungAlle mit kürzlich aktiven Mitarbeitern erhalten
- 14ZusammenfassungAbgleichen und Filtern getrennt halten
4Vorgesetzten folgen und Kombinationen bilden
11 Schritte
Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.
- 1EinführungRollen oder Möglichkeiten wählen
- 2BeispielDie Berichtswege lesen
- 3HerausforderungDie Person an der Spitze erhalten
- 4VerbindungEine weitere Ebene aufsteigen
- 5BeispielKollegenpaare einmal bilden
- 6BeispielSechs Hemdvarianten bilden
- 7HerausforderungDie Auswirkung einer weiteren Eingabe vorhersagen
- 8KernaussageEin vollständiges Berichtsraster erstellen
- 9TippDie fehlende Bedingung ergänzen
- 10HerausforderungPaarungsregeln mit der Produktgröße verbinden
- 11ZusammenfassungJeder Paarung einen klaren Zweck geben
5Einer Zwischentabelle folgen und einen längeren Pfad erhalten
14 Schritte
Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.
- 1EinführungDen Pfad zu den Fakten planen
- 2BeispielDie Einschreibungsverknüpfungen lesen
- 3BeispielDie Zwischentabelle in zwei Schritten durchlaufen
- 4HerausforderungEinen Kurs ohne Studierende finden
- 5ErklärungDen Pfad durch die Ladendaten erweitern
- 6BeispielBestellung 101 in Positionen aufteilen
- 7BeispielDie übrigen Kaufzeilen lesen
- 8HerausforderungDie Produktverknüpfung wählen
- 9BeispielSehen, wie ein späterer Join Kunden entfernt
- 10BeispielDie fehlende Zeile weiterführen
- 11HerausforderungDen Studierenden ohne Einschreibung erhalten
- 12VerbindungEine optionale Gruppe ausdrücklich bilden
- 13HerausforderungDen Filter des fertigen Berichts prüfen
- 14ZusammenfassungDen gesamten Pfad prüfen
6Überhöhte Summen beheben und das Ergebnis prüfen
12 Schritte
Speichere diese Einheit, um jede Interaktive Lektion Schritt für Schritt durchzugehen.
- 1EinführungDie gemessene Größe benennen
- 2BeispielDie Wiederholung einer Bestellsumme verfolgen
- 3TippEinen Wert auf seiner eigenen Ebene summieren
- 4HerausforderungEine Korrektur anhand des Betrags verwerfen
- 5BeispielEine Kennung oder einen Platzhalter zählen
- 6KernaussageZwei Kindlisten vervielfachen sich
- 7ErklärungDie Größenordnung vor dem Ausführen vorhersagen
- 8HerausforderungEinen unvollständigen Schlüssel finden
- 9TippDie Nachschlagetabelle und das Schlüsselformat prüfen
- 10BeispielFehlende Schlüssel nicht durch Gleichheit abgleichen
- 11HerausforderungEine korrekte Kennzahl für den Bericht wählen
- 12ZusammenfassungBedeutung und Anzahlen prüfen
SQL-Joins: Übungsaufgaben
Set 1: Beziehungen lesen und passende Zeilen auswählen10 Übungsfragen
Frage 1 von 10
Antwort zeigenAntwort ausblenden
Frage 2 von 10
a haben den Schlüssel 7. Drei Zeilen in Tabelle b haben den Schlüssel 7. Dies sind die einzigen Zeilen. Wie viele Zeilen gibt a JOIN b ON a.k = b.k zurück?Antwort zeigenAntwort ausblenden
Frage 3 von 10
rentals.customer_ref verweist auf customers.customer_id. Ausleihen haben außerdem ihre eigene rental_id. Welche ON-Bedingung verknüpft jede Ausleihe r mit ihrem Kunden c?Antwort zeigenAntwort ausblenden
Frage 4 von 10
a und b enthalten jeweils account_id und region. Zuvor hatten sie für einen Natural Join nur account_id gemeinsam; region wurde gerade zu b hinzugefügt. Warum kann ein zuvor passendes Paar verschwinden?Antwort zeigenAntwort ausblenden
Frage 5 von 10
(1, North) und (2, South). Die Spiele (match_id, team_id) sind (81, 1) und (82, 1). Welche Namen erscheinen vor dem Filtern bei einem LEFT JOIN von der Teamseite zu den Spielen?Antwort zeigenAntwort ausblenden
Frage 6 von 10
Antwort zeigenAntwort ausblenden
Frage 7 von 10
(id, manager_id): (10, NULL), (11, 10), (12, 10). Ein Self Join verwendet a.manager_id = b.manager_id AND a.id < b.id. Welches ID-Paar wird zurückgegeben?Antwort zeigenAntwort ausblenden
Frage 8 von 10
Antwort zeigenAntwort ausblenden
Frage 9 von 10
authors(author_id) und books(book_id) sind durch book_authors(author_id, book_id) verbunden. Welcher Pfad findet die Bücher eines Autors?Antwort zeigenAntwort ausblenden
Frage 10 von 10
sales(store_id, month) enthält (6, March) und (6, April). targets(store_id, month) enthält dieselben zwei Paare, jeweils einmal. Eine Abfrage verknüpft nur über die Geschäfts-ID und gibt vier Zeilen zurück. Welche Korrektur ergibt einen Zielwert pro Verkauf?Antwort zeigenAntwort ausblenden
Set 2: Zeilen ohne Partner erhalten und Tabellenpfaden folgen10 Übungsfragen
Speichere diese Einheit, um jede Antwort zu sehen und jedes Set zu üben.
Frage 1 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 2 von 10
invoices enthält (invoice_id, client_id): (301, 9), (302, NULL), (303, 12). clients hat die eindeutigen IDs 9 und 12. Welche Rechnungs-IDs bleiben bei einem Inner Join über die Kunden-ID erhalten?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 3 von 10
note darf NULL sein. Welche WHERE-Prüfung findet nach desks LEFT JOIN reservations nur Schreibtische ohne Reservierung?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 4 von 10
departments d LEFT JOIN employees e ON e.department_id = d.department_id. Wohin gehört e.active = 1?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 5 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 6 von 10
memberships(member_id, club_id) erfasst den Beitritt eines Mitglieds zu einem Verein. Wohin gehört joined_on, das Datum dieser bestimmten Mitgliedschaft?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 7 von 10
clients → invoices → lines → services. Jeder Pfeil ist eine Schlüsselverknüpfung und jede service-Zeile ist durch die Service-ID eindeutig. Was stellt eine Detailzeile des Ergebnisses dar, wenn jede Verknüpfung einen Treffer hat?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 8 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 9 von 10
SUM(total) und SUM(DISTINCT total) nach dem Join von Rechnungen mit Positionen?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 10 von 10
code haben. Manche verknüpften Kunden erscheinen zweimal. Welche Diagnoseabfrage findet wiederholte Nachschlagecodes?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Set 3: Filter, Paarungen und wiederholte Werte verfolgen10 Übungsfragen
Speichere diese Einheit, um jede Antwort zu sehen und jedes Set zu üben.
Frage 1 von 10
ON verbindet eine Tabelle mit 4 Spalten und eine Tabelle mit 3 Spalten. Wie breit ist SELECT *, bevor Spalten entfernt werden?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 2 von 10
BETWEEN low AND high Preisbereichen zugeordnet. Die Bereiche sind (0.00, 25.00) und (25.00, 50.00). Wie viele passende Bereichszeilen erzeugt der Betrag?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 3 von 10
suppliers s RIGHT JOIN deliveries d ON d.supplier_id = s.supplier_id und wählt ausdrücklich s.name, d.delivery_id aus. Wie kann sie mit LEFT JOIN dieselben Paare erhalten?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 4 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 5 von 10
<> ab. Wie viele Zeilen werden zurückgegeben und wie viele würde < zurückgeben?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 6 von 10
from_code und to_code, die beide auf airports.code verweisen. Wie sollte ein Bericht beide Flughafennamen abrufen?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 7 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 8 von 10
COUNT(t.task_id) nach teams LEFT JOIN tasks und einer Gruppierung nach Team zurück, wenn Aufgaben-IDs nicht NULL sein können?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 9 von 10
COUNT(article_id) und COUNT(DISTINCT award_id)?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 10 von 10
shipments s LEFT JOIN carriers c über einen passenden Transportunternehmerschlüssel. Eine Sendung hat keinen passenden Transportunternehmer und ein Transportunternehmer hat keine Sendungen. Welcher Datensatz ohne Partner bleibt erhalten?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Set 4: Unvollständige Verknüpfungen und fehlende Zeilen untersuchen10 Übungsfragen
Speichere diese Einheit, um jede Antwort zu sehen und jedes Set zu üben.
Frage 1 von 10
workers.supervisor_ref verweist auf workers.worker_id. Mitarbeiter haben auch eine Spalte name. Was sollte den Mitarbeiteralias w mit dem Vorgesetztenalias s verknüpfen?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 2 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 3 von 10
p über die Konto-ID mit Konten a durch einen Inner Join. Sie wählt nur a.name, p.amount aus. Muss die Konto-ID ebenfalls ausgewählt werden, damit der Join funktioniert?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 4 von 10
a(id, label) und b(id, label) haben die Zeilen (1, red), (2, blue) beziehungsweise (1, red), (2, green). Wie viele Zeilen werden mit JOIN ... USING (id) und wie viele mit NATURAL JOIN zurückgegeben?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 5 von 10
AND r.name = 'East' in ON. Welche Zeilen erscheinen bei der Auswahl von Region und Büro?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 6 von 10
(id, boss_id): (31, NULL), (32, 31), (33, 32), (34, 32). Welche ID-Tripel geben Inner Joins über e.boss_id = m.id und m.boss_id = g.id zurück?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 7 von 10
customers → orders → order_lines → products ist ein Schlüsselpfad. Ein Inner Join aus vier Tabellen verwendet jede Verknüpfung. Warum kann eine Bestell-ID in mehreren Zeilen erscheinen, selbst wenn jeder Primärschlüssel eindeutig ist?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 8 von 10
WHERE service.category = 'Repair'. Die Leistung von A hat die Kategorie Repair. Was bleibt erhalten?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 9 von 10
SELECT DISTINCT name und SELECT DISTINCT subscriber_id, name nach einem Inner Join mit den Zahlungen zurück?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 10 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Set 5: Vollständige Berichte unter veränderten Bedingungen prüfen10 Übungsfragen
Speichere diese Einheit, um jede Antwort zu sehen und jedes Set zu üben.
Frage 1 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 2 von 10
[0.00, 9.00], [10.00, 20.00] und [8.00, 12.00] zugeordnet. Wie ändert sich die Ausgabe für diesen Wert, wenn der dritte Bereich entfernt wird?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 3 von 10
WHERE a.k IS NULL OR b.k IS NULL erhalten?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 4 von 10
WHERE o.date >= '2026-09-01' OR o.order_id IS NULL. Welche Kunden bleiben erhalten?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 5 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 6 von 10
(7,50), (7,60) und (8,50). Eine Abfrage verknüpft members mit memberships und danach clubs jeweils über Left Joins. Wie viele Zeilen gibt es insgesamt und welchen Vereinswert hat Mitglied 9?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 7 von 10
groups LEFT JOIN signups JOIN classes mit groups LEFT JOIN (signups JOIN classes) anhand der jeweiligen Schlüssel. Was geschieht mit H?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 8 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 9 von 10
Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Frage 10 von 10
COUNT(*), COUNT(DISTINCT bill_id) und COUNT(DISTINCT case_id)?Antwort zeigenAntwort ausblenden
Speichere diese Einheit, um diese Antwort zu sehen.
Hängst du bei deiner eigenen Aufgabe fest? Hausaufgabenhilfe
Schlüsselbegriffe
A
Abgleich
abhängige Verknüpfung
abweichendes Schlüsselformat
Aggregationsebene
AND in einer Join-Bedingung
Anti-Join
B
Berichtsraster
Bestellposition
Beziehungsattribut
C
COALESCE
COALESCE(o.total, 0) zeigt null an, wenn die verknüpfte Bestellsumme NULL ist. Wähle die Spaltenbezeichnung daher sorgfältig.COUNT(*)
COUNT(*) bei.COUNT(DISTINCT Schlüssel)
COUNT(Spalte)
COUNT(o.order_id) beiträgt.Cross Join
D
DISTINCT
doppelter Nachschlageschlüssel
E
Eins-zu-eins-Beziehung
Eins-zu-viele-Beziehung
Einschränkung der Join-Partner
ON, welche möglichen Partner als Treffer gelten, während ein Outer Join weiterhin seine erforderlichen Eingabezeilen erhält.ON erhält jeden Kunden, fügt aber nur Bestellungen hinzu, die den Stichtag erfüllen.Einschreibung
Equi-Join
erhaltene Seite
customers c LEFT JOIN orders o unabhängig von der Anzahl der Bestellungen die erhaltene Seite.F
Fan-out
Filter nach dem Join
WHERE auf die vom Join gebildeten Zeilen angewendet und kann sowohl passende als auch mit NULL aufgefüllte Outer-Join-Zeilen entfernen.WHERE entfernt einen Kunden ohne Bestellungen, weil das verknüpfte Bestelldatum dieses Kunden NULL ist.Fremdschlüssel
Full Outer Join
G
geklammerter Join
gemischte Join-Kette
H
Hierarchie
I
Inner Join
IS-NULL-Prüfung
o.order_id IS NULL erhält Kunden ohne Bestellungen; o.order_id = NULL erhält keine Zeilen.J
Join
Join-Bedingung
o.customer_id = c.customer_id paart Bestellung 101, die Kunden-ID 1 enthält, mit der Kundenzeile, deren ID ebenfalls 1 ist.Join-Kette
Join-Pfad
K
kartesisches Produkt
Komma-Join
FROM und drückt ihre Abgleichsbedingung in der WHERE-Klausel der Abfrage aus.L
Left Outer Join
M
mehrdeutige Spalte
JOIN ... ON schlägt die Auswahl von customer_id ohne Qualifizierung fehl, wenn sowohl customers als auch orders die Spalte liefern.mit NULL aufgefüllte Zeile
N
Natural Join
Non-Equi-Join
O
ON-Klausel
optionale Seite
P
Primärschlüssel
customer_id den Datensatz eines Kunden von allen anderen Kundendatensätzen.Q
qualifizierter Spaltenname
c.customer_id wählt den Schlüssel der Kundenseite aus, wenn beide verknüpften Tabellen customer_id enthalten.R
Right Outer Join
S
Selbstpaarung
Self Join
manager_id und der Vorgesetztenalias die passende emp_id.T
Tabellenalias
FROM customers c ermöglicht der Alias c der Abfrage, den Kundennamen als c.name anzusprechen.U
unbeabsichtigter Cross Join
unbekanntes Vergleichsergebnis
ungeordnetes Paar
< erhält es einmal.USING-Klausel
SELECT * einmal an.USING (customer_id) drückt den Abgleich der Kundenschlüssel aus, ohne beide Spaltenverweise auszuschreiben.V
Viele-zu-viele-Beziehung
Vorhersage der Zeilenanzahl
Z
zusammengesetzter Schlüssel
Zwischentabelle
Über diese Einheit
Erstelle deine eigenen Lernmaterialien
Mach aus deinen Notizen, Folien und Dokumenten Lernleitfäden, Übungsfragen, Karteikarten und 6 weitere Tools.