Bislang haben unsere Abfragen nur auf jeweils eine Tabelle zugegriffen. Abfragen können auf mehrere Tabellen gleichzeitig zugreifen oder auf dieselbe Tabelle so zugreifen, dass mehrere Zeilen der Tabelle gleichzeitig verarbeitet werden. Eine Abfrage, die auf mehrere Zeilen der gleichen oder verschiedener Tabellen gleichzeitig zugreift, wird als Join-Abfrage bezeichnet. Nehmen wir als Beispiel an, Sie möchten alle Wetterdatensätze zusammen mit dem Ort der zugehörigen Stadt auflisten. Dazu müssen wir die Spalte „Ort“ jeder Zeile der Wettertabelle mit der Spalte „Name“ aller Zeilen der Tabelle „Städte“ vergleichen und die Zeilenpaare auswählen, bei denen diese Werte übereinstimmen.
Hinweis: Dies ist nur ein konzeptionelles Modell. Die Verknüpfung wird in der Regel effizienter durchgeführt als der tatsächliche Vergleich jedes möglichen Zeilenpaares, aber das ist für den Benutzer nicht sichtbar.
Dies würde durch die folgende Abfrage erreicht werden:
SELECT * FROM weather, cities WHERE city = name;
city | temp_lo | temp_hi | prcp | date | name | location---------------+---------+---------+------+------------+---------------+----------- San Francisco | 46 | 50 | 0.25 | 1994-11-27 | San Francisco | (-194,53) San Francisco | 43 | 57 | 0 | 1994-11-29 | San Francisco | (-194,53)(2 rows)
Beobachten Sie zwei Dinge über die Ergebnismenge:
-
Es gibt keine Ergebniszeile für die Stadt Hayward. Das liegt daran, dass es in der Tabelle
cities
keinen passenden Eintrag für Hayward gibt, so dass die Verknüpfung die nicht übereinstimmenden Zeilen in der Wettertabelle ignoriert. Wir werden gleich sehen, wie das behoben werden kann. -
Es gibt zwei Spalten, die den Ortsnamen enthalten. Das ist korrekt, weil die Spaltenlisten der Tabelle
weather
und der Tabellecities
verkettet sind. In der Praxis ist dies jedoch unerwünscht, so dass Sie wahrscheinlich die Ausgabespalten explizit auflisten wollen, anstatt * zu verwenden:SELECT city, temp_lo, temp_hi, prcp, date, location FROM weather, cities WHERE city = name;
Übung: Versuchen Sie, die Semantik dieser Abfrage herauszufinden, wenn die WHERE-Klausel weggelassen wird.
Da die Spalten alle unterschiedliche Namen hatten, fand der Parser automatisch heraus, zu welcher Tabelle sie gehören, aber es gehört zum guten Stil, Spaltennamen in Join-Abfragen vollständig zu qualifizieren:
SELECT weather.city, weather.temp_lo, weather.temp_hi, weather.prcp, weather.date, cities.location FROM weather, cities WHERE cities.name = weather.city;
Join-Abfragen der bisher gesehenen Art können auch in dieser alternativen Form geschrieben werden:
SELECT * FROM weather INNER JOIN cities ON (weather.city = cities.name);
Diese Syntax ist nicht so gebräuchlich wie die obige, aber wir zeigen sie hier, damit Sie die folgenden Themen besser verstehen.
Jetzt wollen wir herausfinden, wie wir die Hayward-Datensätze wieder reinbekommen. Wir wollen, dass die Abfrage die Tabelle weather
durchsucht und für jede Zeile die passende cities
Zeile findet. Wenn keine übereinstimmende Zeile gefunden wird, sollen die Spalten der cities
-Tabelle durch „leere Werte“ ersetzt werden. Diese Art der Abfrage wird als Outer-Join bezeichnet. (Die Joins, die wir bisher gesehen haben, sind innere Joins.) Der Befehl sieht so aus:
SELECT * FROM weather LEFT OUTER JOIN cities ON (weather.city = cities.name); city | temp_lo | temp_hi | prcp | date | name | location---------------+---------+---------+------+------------+---------------+----------- Hayward | 37 | 54 | | 1994-11-29 | | San Francisco | 46 | 50 | 0.25 | 1994-11-27 | San Francisco | (-194,53) San Francisco | 43 | 57 | 0 | 1994-11-29 | San Francisco | (-194,53)(3 rows)
Diese Abfrage wird linker äußerer Join genannt, weil die Tabelle, die links vom Join-Operator genannt wird, jede ihrer Zeilen mindestens einmal in der Ausgabe hat, während bei der Tabelle rechts nur die Zeilen ausgegeben werden, die mit einer Zeile der linken Tabelle übereinstimmen. Bei der Ausgabe einer Zeile der linken Tabelle, für die es keine Übereinstimmung mit der rechten Tabelle gibt, werden die Spalten der rechten Tabelle durch leere (Null-)Werte ersetzt.
Übung: Es gibt auch Right Outer Joins und Full Outer Joins. Versuchen Sie herauszufinden, was diese bewirken.
Wir können auch eine Tabelle gegen sich selbst verbinden. Dies nennt man einen Self-Join. Nehmen wir als Beispiel an, dass wir alle Wetterdatensätze finden wollen, die im Temperaturbereich anderer Wetterdatensätze liegen. Also müssen wir die Spalten temp_lo und temp_hi jeder weather
Zeile mit den Spalten temp_lo und temp_hi aller anderen weather
Zeilen vergleichen. Wir können dies mit der folgenden Abfrage tun:
SELECT W1.city, W1.temp_lo AS low, W1.temp_hi AS high, W2.city, W2.temp_lo AS low, W2.temp_hi AS high FROM weather W1, weather W2 WHERE W1.temp_lo < W2.temp_lo AND W1.temp_hi > W2.temp_hi; city | low | high | city | low | high---------------+-----+------+---------------+-----+------ San Francisco | 43 | 57 | San Francisco | 46 | 50 Hayward | 37 | 54 | San Francisco | 46 | 50(2 rows)
Hier haben wir die Wettertabelle als W1 und W2 umbenannt, um die linke und rechte Seite des Joins unterscheiden zu können. Solche Aliase können Sie auch in anderen Abfragen verwenden, um sich Tipparbeit zu ersparen, z. B.:
SELECT * FROM weather w, cities c WHERE w.city = c.name;
Sie werden dieser Art der Abkürzung recht häufig begegnen.