JOIN: zwei Tabellen in einer Abfrage
Kurz gesagt: JOIN … ON verbindet eine Zeile einer Tabelle mit der Zeile einer anderen Tabelle, auf die ihr Fremdschlüssel verweist, zum Beispiel eine Bestellung mit ihrem Kunden, und behält nur die Zeilen, die einen Partner haben.
Problem
Bestellungen mit Namen
Der Kurierdienst will eine Liste: Bestellnummer, Datum und Name des Kunden. Nummer und Datum stehen in orders, der Name steht in customers.
In der letzten Lektion haben wir es mit zwei Abfragen gemacht und die Nummer von Hand dazwischen weitergegeben. Bei 60 Bestellungen sind das 60 Nachschlagevorgänge. Wir brauchen eine Abfrage, die den Kunden jeder Bestellung selbst findet.
Die Idee
JOIN … ON
JOIN stellt neben jede Zeile der einen Tabelle die passende Zeile der anderen. ON sagt, welche Zeile zu welcher passt:
Für jede Bestellung sucht die Datenbank den Kunden, dessen customers.id gleich orders.customer_id ist, und klebt beide zu einer Zeile zusammen. Deshalb stehen die Spalten mit dem Tabellennamen davor: orders.id, customers.name.
Es kommen 60 Zeilen heraus, so viele, wie es Bestellungen gibt: Jede Bestellung hat genau einen Kunden. Das heißt JOIN (oder INNER JOIN): Nur die Paare, die gefunden werden, bleiben übrig. Teodora und Yavor stehen nicht in der Liste, weil sie keine Bestellungen haben. Zu ihnen kommen wir in der nächsten Lektion zurück.
An kleinen Tabellen sieht man, wie es geschieht: vier Bestellungen und drei Kunden, und Teodora hat keine Bestellungen.
SELECT orders.id, orders.customer_id, customers.nameFROM ordersJOIN customers ON customers.id = orders.customer_id;Schritt für Schritt, in Worten
- 4 Bestellungen und 3 Kunden. Die customer_id der Bestellung ist die id ihres Kunden.
- Bestellung 1 hat customer_id 2. Die Datenbank sucht den Kunden mit der id 2: Georgi Petrov. Das Paar wird zu einer Zeile.
- Bestellung 2: customer_id 1, das ist Maria Ivanova.
- Bestellung 3 gehört wieder zu Kunde 1: Maria Ivanova steht zum zweiten Mal im Ergebnis.
- Bestellung 4 gehört wieder zu Kunde 2: Georgi Petrov steht zum zweiten Mal im Ergebnis.
- Teodora Genova (id 3) ist die customer_id keiner einzigen Bestellung. Es gibt kein Paar, deshalb steht sie nicht im Ergebnis.
- 4 Zeilen, so viele, wie es Bestellungen gibt. JOIN behält nur die Paare, die gefunden werden.
Dieselbe Abfrage auf diesen kleinen Tabellen. Führe sie aus und vergleiche mit dem letzten Schritt:
Die Idee
Kurze Namen
orders.ordered_at und customers.name werden lang. Einer Tabelle kann man für die Abfrage einen kurzen Namen geben: Du schreibst ihn in FROM und JOIN hinter den Tabellennamen.
Dieselbe Abfrage, dasselbe Ergebnis. o ist orders, c ist customers. Der kurze Name gilt nur in dieser Abfrage. Du kannst auch FROM orders AS o schreiben.
Probier es aus
Die neuen Bestellungen
Zeige die Nummer der neuen Bestellungen (Status new) mit Name und E-Mail des Kunden, damit eine Bestätigung gesendet werden kann.
Lösung
SELECT o.id, c.name, c.email
FROM orders o
JOIN customers c ON c.id = o.customer_id
WHERE o.status = 'new';FROM orders o JOIN customers c ON c.id = o.customer_id WHERE o.status = 'new'. 11 Bestellungen. Die E-Mail steht in customers, ohne JOIN gibt es also keine Möglichkeit, sie neben der Bestellung anzuzeigen.
Sieh es dir an
„ambiguous column name“
Hier eine Abfrage ohne Tabellennamen. Führe sie aus:
Sowohl orders als auch customers haben eine Spalte id. Nach einem JOIN liegen die Spalten beider zusammen, und die Datenbank weiß nicht, welche id du meinst. „Ambiguous“ heißt mehrdeutig: Man kann es auf zwei Arten lesen. Die Spalte name gibt es nur in customers, darüber beschwert sie sich nicht.
Die Lösung: sagen, aus welcher Tabelle die Spalte stammt:
Eine gute Gewohnheit ist, in einer Abfrage mit JOIN vor jede Spalte den kurzen Namen zu setzen, auch wenn es nicht verlangt wird. Wer sie liest, sieht sofort, woher jede Spalte kommt.
Die Idee
JOIN, WHERE und ORDER BY
Nach einem JOIN funktioniert alles, was du kennst, wie bisher, und Bedingungen dürfen Spalten beider Tabellen benutzen. Die Bestellungen der Kunden aus Varna, nach Datum:
Die Stadt steht in customers, das Datum in orders. Die Reihenfolge der Teile ist: SELECT … FROM … JOIN … ON … WHERE … ORDER BY.
Probier es aus
Was in Bestellung 60 steckt
Zeige für jede Position von Bestellung 60 den Produktnamen, die Menge und den Preis.
Lösung
SELECT p.name, oi.quantity, oi.unit_price
FROM order_items oi
JOIN products p ON p.id = oi.product_id
WHERE oi.order_id = 60;FROM order_items oi JOIN products p ON p.id = oi.product_id WHERE oi.order_id = 60. Weißbrot, 2 zu 1,20 €, und Spülmittel, 4 zu 2,90 €. Dasselbe, was wir in der Lektion „Der Shop“ mit den Augen zusammengesetzt haben.
Übung
Zwei Aufgaben
1. Der Shop untersucht, warum Bestellungen storniert werden. Zeige die Nummer der stornierten Bestellungen (cancelled) mit Namen und Stadt des Kunden.
Die stornierten Bestellungen mit dem Kunden und seiner Stadt:
Lösung
SELECT o.id, c.name, c.city
FROM orders o
JOIN customers c ON c.id = o.customer_id
WHERE o.status = 'cancelled';JOIN customers c ON c.id = o.customer_id WHERE o.status = 'cancelled'. 7 Bestellungen. Bestellung 19 gehört Boris, der keine Stadt hat: Der JOIN läuft über die id, die fehlende Stadt stört also nicht, und er kommt mit NULL heraus.
2. Das Qualitätsteam will die Bewertungen mit der Note 3 oder niedriger zusammen mit dem Produktnamen, damit es weiß, was zu prüfen ist.
Die niedrigen Noten: das Produkt, die Note und der Text der Bewertung:
Lösung
SELECT p.name, r.rating, r.body
FROM reviews r
JOIN products p ON p.id = r.product_id
WHERE r.rating <= 3;FROM reviews r JOIN products p ON p.id = r.product_id WHERE r.rating <= 3. Vier Bewertungen: für den Kaffee (1), das Waschpulver (2), die Bratpfanne (3) und das Mineralwasser (3).
Genauer, für Neugierige
Du wirst auch der älteren Form begegnen: Die Tabellen in FROM durch Komma getrennt und die Bedingung für die Paare in WHERE.
Das Ergebnis ist dasselbe. Die Form JOIN … ON hält die Verknüpfungsbedingung getrennt von den Filterbedingungen. Deshalb schreibt der Kurs JOIN.
Test
Teste dich
Verwandte Lektionen
Abschnitt „Verwandte Lektionen“- Baut auf: WHERE: Zeilen filtern · NULL: kein Wert · ORDER BY, LIMIT und DISTINCT · Primärschlüssel und Fremdschlüssel
- Geht weiter in: LEFT JOIN: auch Zeilen ohne Partner · Viele Tabellen und eine Tabelle mit sich selbst verbunden · UNION, INTERSECT, EXCEPT und CROSS JOIN · Unterabfragen
- Aufgaben zum Thema: Tabellen verbinden