Zurück zur Artikelliste Artikel
9 Leseminuten

Anleitung für Anfänger zur SQL-Subquery

Unterabfragen sind eine leistungsstarke SQL-Ressource, die es uns ermöglicht, Daten aus mehreren Tabellen in einer einzigen Abfrage zu kombinieren. In diesem Artikel lernen Sie alles, was Sie für die Verwendung von Unterabfragen brauchen.

Die vielleicht einfachste Definition einer SQL-Subquery ist "Eine Abfrage innerhalb einer Abfrage". Subqueries sind so einfach zu verstehen, dass sie oft in den ersten Kapiteln von SQL-Kursen vorkommen.

Allerdings gibt es viele Varianten von Subqueries, die erklärt werden müssen. Und obwohl Unterabfragen im Allgemeinen in der WHERE-Klausel verwendet werden, können Sie sie auch in anderen Klauseln wie FROM, HAVING und SELECT einsetzen.

Kurz gesagt, es gibt viel mehr über Unterabfragen zu wissen als nur, was sie sind und wohin sie gehören. Beginnen wir also mit unserem ersten Beispiel für eine SQL-Subquery für Anfänger.

Grundlegende Unterabfragen anhand eines Beispiels

Bevor wir uns mit Unterabfragen beschäftigen, müssen wir unsere Datenbanktabellen erläutern. Um unsere Gemüter in dieser Zeit der sozialen Distanzierung zu beruhigen, werde ich Beispiele verwenden, die mit schönen und entspannenden Orten zu tun haben. Unsere Beispieldatenbank wird zwei Tabellen haben. Die erste Tabelle heißt best_10_places und speichert die 10 besten Orte für verschiedene Arten von Aktivitäten (wie Schnorcheln, Skifahren und Wandern). Die Tabelle enthält Spalten für den Namen des Ortes, die Aktivität, die man dort ausüben kann, die Bewertung des Ortes und die nächstgelegene Stadt. Werfen Sie einen Blick darauf:

Place_NameActivityRanking_PositionClosest_City
Praia do Sepulturasnorkeling1Florianopolis
Hanauma Baysnorkeling2Honolulu
Elliot Islandsnorkeling3Melbourne
Cerro Catedralskiing1Bariloche
Camino de Santiagotrekking1Compostela
Cerro Ottotrekking2Bariloche
Black Vulcanotrekking3Honolulu

Tabelle: best_10_places


Wenn Sie zu einem dieser schönen Orte reisen wollen, brauchen Sie ein Ticket; die one_way_ticket Tabelle enthält einen Datensatz für jedes Städtepaar, das durch ein beliebiges Verkehrsmittel verbunden ist. Wir werden diese Tabelle verwenden, um zu ermitteln, wie man von einer Stadt zur anderen kommt. Die Spalten enthalten Informationen über die Ausgangsstadt, die Zielstadt, den Ticketpreis, die Reisezeit und die Art des Verkehrsmittels (z. B. Bahn, Flugzeug usw.). Nachfolgend finden Sie eine Untermenge dieser Tabelle:

City_OriginCity_DestinationTicket_PriceTravel_TimeTransportation
ParisFlorianopolis830.0011hr 30 minair
ParisHonolulu1564.0015hr 20 minair
ParisMelbourne2200.0018hr 50minair
ParisBariloche970.0012hr 20 minair
MadridCompostela80.001hr 10minair

Tabelle: one_way_ticket


Jetzt sind wir bereit für das erste Beispiel. Nehmen wir an, eine Person in Paris möchte zum besten Ort der Welt zum Schnorcheln fahren. Welche Art von Transportmittel führt von Paris zu diesem Ort?

Wie Sie wahrscheinlich wissen, besteht die einfachste SQL-Abfrage aus einer SELECT, einer FROM und (optional) einer WHERE Klausel. Und wie wir bereits erwähnt haben, ist eine Subquery eine Abfrage innerhalb einer Abfrage. Im nächsten Beispiel sehen Sie also zwei Abfragen: die Hauptabfrage (auch äußere Abfrage genannt) und die Unterabfrage(in blau):

SELECT city_destination, transportation, ticket_price, travel_time
FROM one_way_ticket
WHERE city_destination = (
    SELECT closest_city
    FROM best_10_places
    WHERE activity_type = 'snorkeling'
      AND ranking_position = 1
  )
  AND city_origin = 'Paris'

Die Unterabfrage wird zuerst ausgeführt und liefert die closest_city zum besten Schnorchelziel (die Stadt Florianopolis in Brasilien). Dann wird die Hauptabfrage ausgeführt, wobei die Unterabfrage durch ihr Ergebnis (Florianopolis) ersetzt wird. Das Endergebnis ist:

City_DestinationTransportationTicket_PriceTravel_Time
Florianopolisair$ 830.0011hr 30 min

Wenn Sie Unterabfragen verwenden:

  • Sie müssen die Unterabfrage immer in Klammern einschließen.
  • Achten Sie auf den Operator, mit dem Sie das Ergebnis der Unterabfrage vergleichen. In unserem vorherigen Beispiel haben wir "=" verwendet; dieser Operator sollte jedoch bei Unterabfragen verwendet werden, die nur eine Zeile und nur eine Spalte zurückgeben (auch bekannt als "skalare" Unterabfragen).

Ich empfehle Ihnen, den Artikel SQL Subqueries zu lesen, um weitere Beispiele für Subqueries für Anfänger zu sehen, die detailliert erklärt werden. Unterabfragen sind auch Teil unseres SQL für Anfänger Kurses, einem Schritt-für-Schritt-Tutorial, das Sie anhand von Beispielen und Übungen in die Grundlagen von SQL einführt.

Skalare oder nicht-skalare Unterabfragen: Das ist die Frage

Eine skalare Unterabfrage gibt also nur eine Spalte mit nur einer Zeile zurück. Was ist eine nicht-skalare Unterabfrage? Eine Unterabfrage, die mehrere Zeilen zurückgibt.

Es gibt viele Operatoren, mit denen wir eine Spalte mit einer Subquery vergleichen können. Einige von ihnen können jedoch nur mit skalaren Unterabfragen verwendet werden: =, >, >=, < und <=. Wenn Sie einen dieser Operatoren verwenden, muss Ihre Unterabfrage skalar sein.

Sehen wir uns ein Beispiel mit einer skalaren Unterabfrage an. Angenommen, Sie haben einen Kunden, der von Paris nach Bariloche reisen möchte. Bevor er das Ticket kauft, möchte er sehen, ob es Orte gibt, an denen das Ticket günstiger ist. Die folgende Abfrage findet diese Städte:

SELECT city_destination, ticket_price, travel_time, transportation
FROM one_way_ticket
WHERE ticket_price < (
    SELECT ticket_price
    FROM one_way_ticket
    WHERE city_destination = 'Bariloche'
      AND city_origin = 'Paris'
  )
  AND city_origin = 'Paris'

Auch hier wird zuerst die Subquery ausgeführt; ihr Ergebnis (der Preis für ein Ticket Paris-Bariloche, also 970 $) wird mit der Spalte ticket_price in der äußeren Abfrage verglichen. So erhält man alle Datensätze in one_way_ticket mit einem ticket_price Wert kleiner als $970. Das Ergebnis der Abfrage ist unten dargestellt:

City_DestinationTicket_PriceTravel_TimeTransportation
Florianopolis830.0011hr 30 minair
Compostela80.001hr 10minair

Andere Operatoren, wie IN, EXISTS oder NOT EXISTS, > ALL, = ANY, können mit skalaren oder nicht-skalaren Unterabfragen verwendet werden.

Unser nächstes Beispiel verwendet den IN-Operator. Nehmen wir an, dass die Person, die nach dem besten Ort zum Schnorcheln gefragt hat, auch andere Ziele erkunden möchte; tatsächlich möchte sie die drei besten Orte zum Schnorcheln sehen. Die Änderung in unserer Unterabfrage ist klar: Wir müssen nur “ranking_position = 1” mit “ranking_position <= 3” ändern. Unsere Unterabfrage wird jedoch drei Datensätze zurückgeben und ist nicht mehr skalar. Wir werden den IN-Operator verwenden, wie hier:

SELECT city_destination, transportation, ticket_price, travel_time
FROM one_way_ticket
WHERE city_destination IN (
    SELECT closest_city
    FROM best_10_places
    WHERE activity_type = 'snorkeling'
      AND ranking_position <= 3
  )
  AND city_origin = 'Paris'

Wie im vorherigen Beispiel führt die Datenbank zunächst die Unterabfrage aus, die eine Liste von drei Städten zurückgibt (die Städte, die den drei wichtigsten Schnorchelzielen am nächsten liegen: Florianopolis, Honolulu und Melbourne). Dann wird die äußere Abfrage mit diesen Bedingungen ausgeführt:

city_destination IN ('Florianopolis', 'Honolulu', 'Melbourne')

Der Operator IN gibt TRUE zurück, wenn der Wert von city_destination eine dieser drei Städte ist. Die Hauptabfrage gibt also das folgende Ergebnis zurück:

City_DestinationTransportationTicket_PriceTravel_Time
Florianopolisair$ 830.0011hr 30 min
Honoluluair$ 1564.0015hr 20 min
Melbourneair$ 2200.0018hr 50min

Wenn Sie sich eingehender mit den Feinheiten von SQL-Unterabfragen beschäftigen möchten, lesen Sie das Kapitel über Unterabfragen in unserem interaktiven SQL für Anfänger Kurses, in dem Sie mehrere Beispiele und viele praktische Übungen finden.

Erweiterte Unterabfragen

Das Konzept der Unterabfrage ist leicht zu verstehen. Aber aufgrund der Flexibilität von SQL können Unterabfragen in vielen verschiedenen Formen verwendet werden. Es würde den Rahmen dieses Artikels sprengen, alle möglichen Verwendungszwecke zu behandeln. Wir werden stattdessen einige der wichtigsten Verwendungsmöglichkeiten aufzeigen.

An wie vielen verschiedenen Stellen kann man eine Subquery einsetzen?

Unterabfragen können an verschiedenen Stellen in einer SQL-Abfrage verwendet werden, z. B. in den Klauseln WHERE, FROM, HAVING und SELECT. Darüber hinaus kann eine Unterabfrage auch als Teil einer Anweisung UPDATE, DELETE oder INSERT verwendet werden. Im nächsten Beispiel sehen wir, wie eine Subquery in der FROM -Klausel verwendet werden kann.

Angenommen, der Inhaber des Reisebüros möchte jede Stadt zusammen mit den Ticketkosten und der Anzahl der "besten Orte" in der Nähe dieser Stadt anzeigen. Um die Anzahl der "besten Plätze" für jede Stadt zu erhalten, werden wir eine Unterabfrage (blau dargestellt) in der FROM-Klausel verwenden, um eine Pseudotabelle zu erstellen. Dann wird die äußere Abfrage JOIN mit one_way_ticket und der Pseudo-Tabelle.

SELECT city_destination, ticket_price, pseudo_table.quantity
FROM one_way_ticket
JOIN (
    SELECT closest_city AS city, count(*) AS quantity
    FROM best_10_places
    GROUP BY 1
  ) pseudo_table
  ON one_way_ticket.pseudo_table.city

Das Ergebnis dieser Abfrage ist:

City_DestinationTicket_PriceQuantity
Florianopolis830.001
Honolulu1564.002
Melbourne2200.001
Bariloche970.002
Compostela80.001

Weitere Informationen über die Verwendung von Subqueries in anderen SQL-Anweisungen finden Sie unter Subqueries in UPDATE- und DELETE-Anweisungen. Dieser Artikel enthält mehrere Beispiele mit SQL-Code, den Sie kopieren und einfügen können, wenn Sie ihn ausprobieren möchten.

EXISTS: Ein subquery-orientierter Operator

Einer der leistungsfähigsten Operatoren, die Sie mit Unterabfragen verwenden können, ist der EXISTS Operator. Wie im folgenden Beispiel zu sehen ist, muss der Operator EXISTS vor der Unterabfrage stehen. Er gibt TRUE zurück, wenn die Unterabfrage mindestens eine Zeile zurückgibt - unabhängig vom Inhalt der Zeile. Wenn die Unterabfrage 0 Zeilen liefert, gibt EXISTS FALSE zurück.

Nehmen wir als nächstes Beispiel an, dass unser Kunde aus Paris an einen Ort reisen möchte, an dem er sowohl wandern als auch schnorcheln kann. Die folgende Abfrage kann verwendet werden, um diesem Kunden zu antworten:

SELECT city_destination, transportation, ticket_price, travel_time
FROM one_way_ticket
WHERE EXISTS (
    SELECT closest_city
    FROM best_10_places
    WHERE activity_type = 'snorkeling'
      AND closest_city = one_way_ticket.city_destination
  )
  AND EXISTS (
    SELECT closest_city
    FROM best_10_places
    WHERE activity_type = 'trekking'
    AND closest_city = one_way_ticket.city_destination
  )
  AND city_origin = 'Paris'

Das Ergebnis zeigt die Datensätze, die sich auf Städte mit Trekking- und Schnorchelaktivitäten beziehen:

City_DestinationTransportationTicket_PriceTravel_Time
Honoluluair$ 1564.0015hr 20 min

Ein interessanter Punkt in der vorherigen Unterabfrage ist der Verweis auf die Spalte one_way_ticket.city_destination in der äußeren Abfrage. Unterabfragen, die auf Spalten in der äußeren Abfrage verweisen, werden als "korrelierte Unterabfragen" bezeichnet und haben einige spezifische Verhaltensweisen. Wie im vorherigen Beispiel werden korrelierte Unterabfragen meist mit den Unterabfrageoperatoren EXISTS und NOT EXISTS verwendet.

Korrelierte Unterabfragen sind eine leistungsstarke SQL-Ressource. In bestimmten Szenarien sind sie der natürliche Weg, um ein Problem zu lösen. Wenn Sie sich für dieses Thema interessieren, empfehle ich Ihnen das Buch Korrelierte Unterabfrage in SQL: Ein Leitfaden für Einsteiger und SQL-Subqueries in 5 Minuten schreiben lernen.

Die Operatoren ALL und ANY

Diese beiden Operatoren arbeiten zusammen mit den Operatoren =, <>, >, >=, < und <= und verleihen der Sprache mehr Ausdruckskraft. Aufgrund der großen Anzahl möglicher Kombinationen mit ALL und ANY habe ich eine Tabelle mit den häufigsten Verwendungen dieser Operatoren beigefügt:

ConditionReturns TRUE if ...Returns FALSE if ...
Where 10 > ANY ( subquery )The subquery returns at least one value that’s greater than 10.All returned values are 10 or less.
Where 10 > ALL ( subquery )The subquery returns only values greater than 10.The subquery returns at least one value of 10 or less.
Where 10 = ANY (subquery)The subquery returns at least one value equal to 10.No returned values are equal to 10.
Where 10 = ALL (subquery)All values returned by subquery are 10.At least one returned value is not equal to 10.

Wenden wir diesen Operator auf ein Beispiel aus dem wirklichen Leben an. Nehmen wir an, wir möchten alle "weltbesten Orte", die man mit einem Ticket unter 1.000 Dollar besuchen kann, anzeigen. Jeder "beste Ort" in der Tabelle best_10_places kann viele mögliche Tickets haben; wir sind nur an den Orten interessiert, an denen mindestens ein Ticket weniger als 1000 Dollar kostet. Die Abfrage lautet wie folgt:

SELECT Place_name, Activity, Ranking_position
FROM best_10_places
WHERE 1000 > ANY (
    SELECT ticket_price
    FROM one_way_ticket
    WHERE city_destination = best_10_places.closest_city
  )

Die Ergebnisse der vorangegangenen Abfrage sind unten aufgeführt. Sie können den besten Ort für jede Aktivität (Schnorcheln, Skifahren und Trekking) für weniger als 1.000 $ besuchen!

Place_NameActivityRanking_Position
Praia do Sepulturasnorkeling1
Cerro Catedralskiing1
Camino de Santiagotrekking1
Cerro Ottotrekking2

Ihre nächsten Schritte mit Unterabfragen

In diesem Artikel habe ich Unterabfragen erklärt und Ihnen mehrere Beispiele für ihre Verwendung gezeigt. Dennoch gibt es bei diesem Thema viele Variationen, einschließlich der verschiedenen Arten von Unterabfragen und Operatoren. Um ein umfassenderes Verständnis von Unterabfragen zu erlangen, empfehle ich einen Online-Kurs wie den von LearnSQL.de SQL für Anfänger oder die zusätzlichen Artikel zu lesen, die ich erwähnt habe.