MySQL LEFT Join
Mittels dem JOIN-Statement lassen sich die Werte aus mehreren Tabellen kombinieren. Statt also mehrere individuelle SQL-Statements an die Datenbank zu senden, wird so ein einzelnes Statement gesendet und es werden mehrere Tabellen zugleich abgefragt. Damit der JOIN der Tabellen funktioniert, müssen diese über eine gemeinsame Spalte verbunden miteinander sein. In MySQL stehen vier JOIN-Typen zur Verfügung: INNER JOIN, LEFT JOIN, RIGHT JOIN und FULL JOIN. Dabei ist der LEFT JOIN aus meiner Perspektive der nützlichste und am leichteste zu verstehende Join und in über 10 Jahren Webentwicklung habe ich die weiteren Join-Typen noch nicht benötigt.
Die Syntax für einen LEFT JOIN ist wie folgt:
1 2 3 4 |
SELECT * FROM tabelle1 LEFT JOIN tabelle2 ON tabelle1.Spaltenname = tabelle2.Spaltenname LEFT JOIN tabelle3 ON tabelle1.Spaltenname = tabelle3.Spaltenname WHERE ... |
Ihr könnt beliebig viele JOIN-Statements aneinanderreihen.
Inhaltsverzeichnis
Beispiel für LEFT JOIN
Angenommen ihr habt eine User-Tabelle sowie eine Kommentar-Tabelle. Diese sehen wie folgt aus:
1 2 3 4 5 6 7 8 |
Tabelle 'users' Tabelle 'kommentare' +--+-------+--------+ +--+---------+------+---------------+ |id|vorname|nachname| |id|beitragid|userid|text | +--+-------+--------+ +--+---------+------+---------------+ | 1| Max | Müller | | 1| 1| 1| Toller Artikel| | 2| Lisa | Schmidt| | 2| 2| 1| Super | | 3| Klaus | Taler | | 3| 1| 2| Nix verstanden| +--+-------+--------+ +--+---------+------+---------------+ |
Möchtet ihr nun alle Kommentare für Beitrag 1 ausgeben sowie den Vor- und Nachnamen des Autors, so wäre eine mögliche Lösung für jeden Kommentar ein neuen Query für die users-Tabelle zu senden. Dies führt allerdings zu unübersichtlichem Code und ist außerdem noch recht ineffizient, denn pro Kommentar muss ein neuer Query an die Datenbank gesendet werden.
Mittels LEFT JOIN lassen sich nun beide Tabellen in einem einzigen Query abfragen:
1 2 3 4 5 6 7 8 9 10 11 |
SELECT kommentare.*, users.vorname, users.nachname FROM kommentare LEFT JOIN users ON kommentare.userid = users.id WHERE beitragid = 1 Ergebnis +--+---------+------+--------------+----------------+ |id|beitragid|userid|text |vorname|nachname| +--+---------+------+--------------+----------------+ | 1| 1| 1|Toller Artikel|Max |Müller | | 3| 1| 2|Nix verstanden|Lisa |Schmidt | +--+---------+------+--------------+----------------+ |
Im obigen Statement wird mittels LEFT JOIN neben der kommentare Tabelle ebenfalls die users Tabelle abgefragt. Als Bedingung wird die id-Spalte der users-Tabelle und die userid-Spalte der kommentare-Tabelle definiert.
Konkret läuft dieser Query so ab, dass die kommentare Tabelle abgefragt wird und dann wird in der User-Tabelle nachgeschaut, ob ein User mit einer passenden id zu dem Wert in der kommentare.userid gefunden werden kann.
Als ausführbarer PHP Code mit PDO sieht dies wie folgt aus:
<?php $pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'password'); $statement = $pdo->prepare("SELECT kommentare.*, users.vorname, users.nachname FROM kommentare LEFT JOIN users ON kommentare.userid = users.id WHERE beitragid = 1"); $statement->execute(array('beitragid' => 1)); while($kommentar = $statement->fetch()) { echo $kommentar['vorname']." ".$kommentar['nachname']." schrieb:<br />"; echo $kommentar['text']."<br /><br />"; } ?>
Die Spalten der Tabellen die ihr so per JOIN hinzugefügt habt lassen sich auch für die WHERE-Klausel oder die ORDER-BY-Klausel nutzen:
1 2 3 4 |
SELECT kommentare.*, users.vorname, users.nachname FROM kommentare LEFT JOIN users ON users.id = kommentare.userid WHERE beitragsid = 1 AND vorname= 'Max' ORDER BY users.id |
Im obigen Script werden nur Kommentare von Benutzern ausgegeben, die mit Vornamen Max heißen. Das ganze wird anhand der User-ID sortiert.
Gleichbenannte Spaltennamen bei JOINs
Eine Herausforderung bei JOINs sind gleichbenannte Spaltennamen in verschiedenen Tabellen. Um die Ergebnisse des SELECT-Queries abzufragen, müssen die Spaltennamen eindeutig sein. Fragt ihr zwei Tabellen ab die eine Spalte mit dem selben Namen besitzen, so könnt ihr allerdings auf das Schlüsselwort AS zurückgreifen, um die Spalten im Query umzubenennen. Nachfolgend ein Beispiel.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
SELECT buecher.name AS buch_name, autoren.name AS autor_name FROM buecher LEFT JOIN autoren ON autoren.id = buecher.autorid Tabelle 'buecher' Tabelle 'autoren' +--+-------+--------------+ +--+--------------+ |id|autorid|name | |id|name | +--+-------+--------------+ +--+--------------+ | 1| 1|Herr der Ringe| | 1|J.R.R. Tolkien| | 2| 1|Der Hobbit | | 2|J.K. Rowling | | 3| 2|Harry Potter | +--+--------------+ +--+-------+--------------+ Ergebnis: +--------------+--------------+ |buch_name |autor_name | +--------------+--------------+ |Herr der Ringe|J.R.R. Tolkien| |Der Hobbit |J.R.R. Tolkien| |Harry Potter |J.K. Rowling | +--------------+--------------+ |
Im obigen Query wird die Spalte name von der Tabelle bucher in buch_name und die Spalte name der Tabelle autoren in autor_name umbenannt. Auf diese Spalten könnt ihr dann in PDO wie gewohnt mittels $row->buch_name bzw. $row->autor_name zugreifen.
INNER JOIN und RIGHT JOIN
Bei einem LEFT JOIN werden stets alle Zeilen der Tabelle zurückgegeben, die beim FROM aufgeführt sind. Diese Tabelle stellt die Basis für das Ergebnis. Sollte in der Tabelle die per JOIN hinzugefügt werden kein passender Eintrag gefunden werden, im obigen Beispiel beispielsweise kein Autor zu einer entsprechenden Autoren-ID, so erhalten diese Felder den NULL Wert.
Ein RIGHT JOIN verhält sie wie ein LEFT JOIN, nur dass in dem Fall die Tabelle die im JOIN hinzugefügt wird als Basis dient. Jeder RIGHT JOIN kann auch als LEFT JOIN geschrieben werden kann und da ein LEFT JOIN intuitiver ist, sollte man lieber auf RIGHT JOIN verzichten.
Ein INNER JOIN verhält sich dagegen etwas anders. Dort muss eine passende Zeile in der Tabelle gefunden werden- Sprich, wird für die buecher-Tabelle kein Autor mit der entsprechenden ID gefunden, so wird dieser Datensatz nicht zurückgegeben.
Autor: Nils Reimers