Zurück zur Artikelliste Artikel
10 Leseminuten

Der SQL EXISTS-Operator

Die Verwendung der SQL EXISTS-Klausel können wir komplexe Abfragen auf einfache Weise erstellen. Lernen Sie in diesem Artikel die Vor- und Nachteile des EXISTS-Operators in diesem Artikel.

In SQL hilft der EXISTS Operator bei der Erstellung logischer Bedingungen in unseren Abfragen. Im Wesentlichen prüft er, ob Zeilen in einer Unterabfrage vorhanden sind. Wir zeigen Ihnen die Syntax von EXISTS, geben Ihnen einige Beispiele für die Verwendung und geben Ihnen dann einige Übungen zum Üben an die Hand.

Wenn Sie gerade erst mit SQL anfangen oder eine SQL-Auffrischung brauchen, empfehle ich Ihnen den Kurs SQL für Anfänger. Er umfasst SQL-Themen, die von grundlegenden SELECTs bis hin zu komplexen Themen wie Joins, Aggregationen und Unterabfragen reichen. Es ist eine gute Möglichkeit, Ihre SQL-Kenntnisse aufzubauen, aufzufrischen oder zu erweitern.

Syntax des EXISTS-Operators

Sie sind wahrscheinlich mit SQL-Operatoren wie =, >, < und LIKE vertraut. Alle diese Operatoren können verwendet werden, um logische Bedingungen zu erstellen, die TRUE oder FALSE zurückgeben. Beispiele für übliche Bedingungen sind:

WHERE Employee_id = 10345
WHERE Price < 1000
WHERE Name LIKE ‘John%’

Die Operatoren =, < und LIKE vergleichen zwei Elemente oder Operanden. Aus diesem Grund werden sie auch als binäre Operatoren bezeichnet.

				WHERE EXISTS ( subquery )

Schauen wir uns nun die gesamte SQL-Abfrage an, um festzustellen, wo die Bedingung EXISTS platziert werden kann:

SELECT columns
FROM table1
WHERE EXISTS (SELECT columns FROM table2);

Der EXISTS Operator wird verwendet, um boolesche Bedingungen zu erstellen, um zu überprüfen, ob eine Unterabfrage Zeilen oder eine leere Menge zurückgibt. EXISTS gibt TRUE zurück, wenn seine Unterabfrage mindestens eine Zeile zurückgibt. Es spielt keine Rolle, wie viele Zeilen zurückgegeben werden oder wie viele Spalten sich in der Liste der Unterabfrage SELECT befinden. Nur wenn die Unterabfrage 0 Zeilen zurückgibt, gibt EXISTS FALSE zurück. Es ist wichtig zu beachten, dass keine der von der Unterabfrage zurückgegebenen Zeilen im Endergebnis angezeigt wird.

Beispiel Datenbank: Luxusboote und Autos

Schauen wir uns einige Beispielabfragen an, die auf einer Beispieldatenbank eines Unternehmens basieren, das Luxusautos und -boote verkauft. Das Unternehmen führt eine Übersicht über die Autos und Boote in der Tabelle product, die die Spalten product_id, product_name, product_price, product_type enthält.

product_idproduct_nameproduct_priceproduct_type
100Ferrari F203000000Car
101Lamborghini AX3600000Car
102Pagani Zonda4300000Car
200VanDutch 582100000Boat
201Lamborghini B93400000Boat
202VanDutch 561800000Boat
300Boat Engine Yamei 1001000000Boat

Die Datenbank hat auch eine Client Tabelle mit den Spalten client_id, client_name und country.

client_idclient_namecountry
10John F.United States
11Samid A,Kuwait
12Majal H.Brunei
13Pierre B.France
14Abdul E.Kuwait

Schließlich gibt es noch die sale mit den Spalten product_id, client_id, sale_date. (Der Einfachheit halber lasse ich die Idee einer Tabelle für Bestellungen weg; in dieser Art von Unternehmen kauft ein Kunde normalerweise nur ein Produkt auf einmal).

client_idproduct_idcountry
102002020-03-05
101012024-04-05
112022023-03-05
121022021-03-07
121002023-03-05
122022024-04-09
133002022-03-05
103002020-07-19
133002023-11-25

Beispiele für den SQL EXISTS-Operator

Beispiel 1: Suche nach verkauften Produkten

Angenommen, der Marketingleiter möchte wissen, welche Autos und Boote zwischen dem 1. und 15. April 2024 verkauft wurden. Die folgende Abfrage erfüllt diesen Zweck:

SELECT product_name 
FROM product p1
WHERE EXISTS ( SELECT * FROM sale s 
               WHERE  s.product_id = p1.product_id 
               AND    s.sale_date >= ‘2024-04-01’ 
               AND    s.sale_date <= ‘2024-04-15’
             )

Ergebnisse:

Product_name
Lamborghini AX
VanDutch 56

Es gibt andere Möglichkeiten, diese Abfrage zu schreiben, ohne den Operator EXISTS zu verwenden. Um jedoch zu erklären, wie der EXISTS Operator funktioniert, ist dies ein gutes Einstiegsbeispiel.

Die Hauptabfrage SELECT ist sehr einfach; sie geht in die Tabelle product um die Spalte product_name zu erhalten. Wir wollen jedoch nicht alle product_names in der Tabelle haben. Wir wollen nur die Produkte, die TRUE für die folgende Bedingung liefern:

WHERE EXISTS ( SELECT * FROM sale s 
               WHERE  s.product_id = p1.product_id 
               AND     s.sale_date >= ‘2024-04-01’ 
               AND     s.sale_date <= ‘2024-04-15’
             )

Wenn wir die Bedingung analysieren, gibt die Subquery alle Verkaufsdatensätze für ein bestimmtes Produkt (p1.product_id) und für einen bestimmten Zeitraum (2024-04-01 bis 2024-04-15) zurück. Wenn die Unterabfrage Datensätze zurückgibt, dann gibt EXISTS TRUE zurück. Wenn die Unterabfrage keine Datensätze liefert, dann gibt EXISTS FALSE zurück. Beachten Sie, dass die Unterabfrage viele Male ausgeführt wird - einmal für jede Zeile, die von der externen Abfrage gelesen wird.

Diese Art von Unterabfragen, die für jede in der Hauptabfrage verarbeitete Zeile einmal ausgeführt werden, nennt man "korrelierte Unterabfragen", und sie haben ihre Besonderheiten. Wenn Sie sich eingehender mit diesem Thema befassen möchten, empfehle ich Ihnen den Artikel Correlated Subquery in SQL: A Beginner's Guide.

Beispiel 2: Verwendung des NOT EXISTS-Operators

Nehmen wir an, der Manager möchte die Namen der Fahrzeuge wissen, die im gleichen Zeitraum nicht verkauft wurden. Diese Art von Abfrage - bei der nach Datensätzen gesucht wird, die nicht in der Datenbank vorhanden sind - eignet sich hervorragend für den Operator NOT EXISTS. Schließlich suchen wir nach Elementen, die nicht in der Datenbank vorhanden sind. Die Abfrage lautet wie folgt:

SELECT * FROM product p1
WHERE p1.product_type = ‘Car’
AND   NOT EXISTS ( SELECT * FROM sale s
                   WHERE s.product_id = p1.product_id
                   AND   s.sale_date >= ‘2024-04-01’ 
                   AND   s.sale_date <= ‘2024-04-15’
                 )

Ergebnisse:

Product_idProduct_nameProduct_priceProduct_type
100Ferrari F203000000Car
102Pagani Zonda4300000Car

Wenn wir einmal verstanden haben, wie der EXISTS Operator in SQL funktioniert, ist das Verständnis von NOT EXISTS sehr einfach; es ist das Gegenteil. Wenn EXISTS TRUE zurückgibt, dann gibt NOT EXISTS FALSE zurück und andersherum.

In diesem Beispiel hat die Hauptabfrage eine WHERE Klausel mit zwei Bedingungen. Die erste Bedingung besteht darin, nach Produkten des Typs "Fahrzeug" zu suchen. Die zweite Bedingung verwendet NOT EXISTS, um nur die Produkte zu behalten, die im Zeitraum vom 2024-04-01 bis 2024-04-15 keine Verkäufe hatten. Mit anderen Worten, wir suchen nach Produkten, für die die Unterabfrage eine leere Ergebnismenge liefert - d. h. für die es in diesem Zeitraum keine Verkäufe gibt.

In einigen Fällen können wir diese Art von Abfrage mit NOT IN und einer Unterabfrage lösen. In dieser speziellen Abfrage können wir diese WHERE Klausel einfügen:

WHERE p1.product_type = ‘Car’
AND   p1.product_id NOT IN (SELECT s.product_id 
                            FROM  sale s
               WHERE s.sale_date >= ‘2024-04-01’ 
                            AND   s.sale_date <= ‘2024-04-15’
                           )

Es gibt jedoch einen Unterschied in der Art und Weise, wie die Abfrage intern in der Datenbank ausgeführt wird. Die Bedingung der Unterabfrage NOT IN wird einmal ausgeführt, während die Bedingung der Unterabfrage NOT EXISTS für jede Zeile einmal ausgeführt wird. Das ist richtig; NOT EXISTS ist eine korrelierte Subquery. Lesen Sie die Artikel 5 SQL Subquery Examples und SQL IN Operator, um mehr über diese Operatoren zu erfahren.

Beispiel 3: Verwendung von EXISTS mit NOT EXISTS

Als Nächstes benötigen wir eine Liste der Kunden, die im Sommer 2023 kein Boot gekauft haben, aber im vorangegangenen Winter (d. h. Dezember 2022 bis März 2023) ein Boot gekauft haben. Die Abfrage, um diesen Bericht zu erhalten, lautet:

SELECT * 
FROM   client c1
WHERE  EXISTS ( SELECT * FROM sale s1 
                JOIN  product p1 ON p1.product_id = s1.product_id
                WHERE c1.client_id = s1.client_id
                AND p1.product_type = 'Boat'
                AND s1.sale_date >= '2022-12-21' 
                AND s1.sale_date <= '2023-03-20' -- winter
              )
AND    NOT EXISTS ( SELECT * FROM sale s2
                   JOIN  product p1 ON p1.product_id = s2.product_id 
                   WHERE c1.client_id = s2.client_id
                   AND p1.product_type = 'Boat' 
                   AND s2.sale_date >= '2023-6-21' 
                   AND s2.sale_date <= '2023-09-20' -- summer
                  ) ;

Ergebnisse:

client_idClient_nameCountry
11Samid A.Kuwait

Nach den beiden vorangegangenen Beispielen sollte dieses Beispiel nicht allzu schwer zu verstehen sein; es ist die Kombination aus beiden. Die Idee ist, den gesamten Datensatz (SELECT *) aus der Tabelle client Tabelle auszuwählen und dann eine EXISTS zu verwenden, um zu überprüfen, ob ein Boot im letzten Winter gekauft wurde. Danach verwenden wir NOT EXISTS, um zu prüfen, dass im vergangenen Sommer kein Boot gekauft wurde. Beachten Sie, dass beide Unterabfragen ein JOIN zwischen den sale und product steht, weil wir die Spalten product_type und sale_date in den WHERE Bedingungen verwenden müssen.

An dieser Stelle möchte ich etwas über korrelierte Unterabfragen klarstellen. Wir haben erwähnt, dass korrelierte Unterabfragen für jeden Zeilenkandidaten ein Mal ausgeführt werden. Diese Tatsache kann sich auf die Leistung der gesamten Abfrage auswirken, insbesondere wenn wir mit großen Tabellen arbeiten.

Zusammenfassend lässt sich sagen, dass der Operator EXISTS (und korrelierte Unterabfragen) eine leistungsstarke SQL-Ressource für bestimmte Arten von Abfragen ist. Wir sollten jedoch korrelierte Unterabfragen vermeiden, wenn wir mit großen Tabellen arbeiten.

Üben des EXISTS-Operators

Wie bei vielen anderen Computersprachen ist das Erlernen von SQL durch Übungen eine der besten Methoden, um Fähigkeiten zu erwerben. In diesem Abschnitt zeige ich drei EXISTS Operator-Übungen von unterschiedlicher Komplexität.

Übung 1: Alte Befehle

Übung: Der Inhaber des Unternehmens möchte wissen, welche Produkte (Autos oder Boote) in den letzten 365 Tagen nicht bestellt wurden.

Lösung:

	 SELECT p1.product_name
       FROM  product p1
       WHERE NOT EXISTS ( SELECT 1 FROM sale s
                          WHERE  s.product_id = p1.product_id
                          AND    s.sale_date >= CURRENT_DATE - 365
                        );

Ergebnisse:

Product_name
Ferrari F20
Pagani Zonda
Lamborghini B9
VanDutch 58

Erläuterung: Die Hauptabfrage verwendet die Tabelle product um die Spalte product_name zu erhalten. Die WHERE Klausel dieser Abfrage ist der Schlüsselteil. Sie hat eine NOT EXISTS Bedingung, die TRUE für die Produkte auswertet, die im letzten Jahr nicht verkauft wurden. Mit der Bedingung s.sale_date >= CURRENT_DATE - 365 in der Unterabfrage werden alle Zeilen des letzten Jahres abgerufen.

Beachten Sie, dass die Unterabfrage eine Konstante ( 1 ) zurückgibt. Das liegt daran, dass es bei der Unterabfrage darauf ankommt, wie viele Zeilen sie zurückgibt, und nicht auf den Inhalt der zurückgegebenen Zeilen; daher können wir eine Spalte oder eine Konstante wie 1 verwenden.

Übung 2: Käufer von Bootsmotoren

Übung: Unser Unternehmen ist bekannt für die Herstellung eines Bootsmotors und wir haben einige Kunden, die nur dieses Produkt kaufen. Die Marketingabteilung möchte Kunden identifizieren, die nur Bootsmotoren kaufen, damit sie diese Kunden in einer Marketingkampagne ansprechen können.

Lösung:

SELECT * FROM client c1
WHERE EXISTS ( SELECT * FROM sale s1  -- they buy boat engines
		   JOIN  product p1 ON p1.product_id = s1.product_id 
                WHERE c1.client_id = s1.client_id
                AND   p1.product_name = 'Boat engine'   
               )
AND NOT EXISTS ( SELECT * FROM sale s2  -- they never buy other product
                 JOIN  product p2 ON p2.product_id = s2.product_id 
		    WHERE c1.client_id = s2.client_id
                 AND p2.product_name <> 'Boat engine' 
                );

Ergebnisse:

client_idClient_nameCountry
13Pierre B.France
14Abdul E.Kuwait

Erläuterung: Diese Übung hat eine WHERE Klausel mit zwei Bedingungen. Die erste Bedingung verwendet einen EXISTS Operator, um zu überprüfen, ob der von der äußeren Abfrage ausgewählte Kunde einen Bootsmotor gekauft hat. Die zweite Bedingung WHERE verwendet NOT EXISTS, um zu überprüfen, dass derselbe Kunde (der von der äußeren Abfrage ausgewählte Kunde) noch nie eine andere Art von Produkt gekauft hat.

Wenn Sie weitere Übungen zu Subqueries kennenlernen möchten, empfehle ich Ihnen den Artikel SQL Subquery Practice: 15 Exercises with Solutions.

Übung 3: Nie gekauft

Übung: Der Eigentümer des Unternehmens möchte einen Bericht über nie gekaufte Produkte erstellen. Der Bericht soll nur zwei Spalten enthalten: client_name und product_name. Der Inhalt des Berichts soll das Komplement der sale Tabelle sein. Mit anderen Worten: Wenn ein Kunde nie ein Produkt gekauft hat, dann muss das Paar aus client_name und product_name im Bericht enthalten sein.

Lösung: Es gibt zwei Wege, diese Aufgabe zu lösen:

  • Verwendung von NOT EXISTS.
  • Verwendung des Mengenoperators EXCEPT (oder MINUS).

Wir werden beide Ansätze zeigen.

Lösung mit NOT EXISTS:

SELECT c1.client_name, p1.product_name
FROM client c1, product p1
WHERE NOT EXISTS ( SELECT 1 FROM sale s 
                   WHERE c1.client_id = s.client_id
                   AND   p1.product_id = s.product_id  
                 )

Teilweise Abfrageergebnisse:

Client_nameProduct_name
John F.Ferrari F20
John F.Pagani Zonda
John F.Lamborghini B9
John F.VanDutch 56
Samid A.Lamborghini AX
Samid A.Pagani Zonda
Samid A.VanDutch 56
Samid A.Lamborghini B9
Samid A.Boat Engine Yamei 100
Samid A.Ferrari F20

Erläuterung: Der erste Punkt, den es zu verstehen gilt, ist das Ergebnis dieses Teils der Abfrage:

SELECT c1.client_name, p1.product_name
FROM client c1, product p1

Da wir die Tabellen nicht richtig verbinden client und productnicht richtig verbunden haben, ist das Ergebnis ein kartesisches Produkt - eine Menge aller möglichen <client_name, product_name> Paare.

Sobald wir alle möglichen Paare haben, verwerfen wir diese Paare in der sale Tabelle zu verwerfen, indem wir den Operator NOT EXISTS verwenden.

Lösung mit EXCEPT:

SELECT c1.client_name, p1.product_name
FROM client c1, product p1
EXCEPT
SELECT client_name, product_name 
FROM sale s
JOIN product p ON p.product_id  = s.product_id
JOIN client c ON c.client_id = s.client_id

Erläuterung: Der erste Teil dieses Ansatzes ähnelt der vorherigen Lösung; wir erstellen alle möglichen Kunden-Produkt-Paare. Dann entfernen wir mit dem Operator EXCEPT die Paare, die sich in der sale Tabelle stehen. So erhalten wir die gesuchten Paare.

Hier ist der Unterschied: Im zweiten Teil von EXCEPT müssen wir JOIN die sale Tabelle mit den product und client Tabellen.

Erweitern Sie Ihre SQL EXISTS-Operator-Kenntnisse

In diesem Artikel haben wir die Operatoren EXISTS und NOT EXISTS anhand mehrerer Beispiele behandelt. Wir haben auch die Vor- und Nachteile von korrelierten Unterabfragen erläutert. Lesern, die ihre SQL-Kenntnisse vertiefen wollen, empfehle ich den SQL-Praxis Titel. Sie werden Hunderte von Übungen zu SQL-Themen wie JOINs, GROUP BY, HAVING, Unterabfragen und sogar den EXISTS-Operator finden.

Wenn Sie gerade erst mit SQL anfangen oder eine Auffrischung brauchen, empfehle ich unseren SQL für Anfänger Kurs. Wenn Sie Ihre SQL-Kenntnisse verbessern, investieren Sie in sich selbst!