<< >> Up Title Contents Index

IN, ALL, ANY, EXISTS

Die Anfrage

SELECT nachname, plz, ort, konto
       FROM kunde
       WHERE konto =
       (SELECT MAX(konto)
               FROM kunde)

ergibt die Tabelle:

Die Anfrage ermittelt den Kunden mit dem höchsten Kontostand.

Die zweite SELECT-Anweisung, eingeschlossen in Klammern, heißt innere Abfrage. Sie ist eine vollständige SQL-Abfrage für sich. Durch ihre Ausführung wird ein Wert oder eine Menge von Werten als Teil der Hauptabfrage erzeugt und diese dadurch vervollständigt, um aus ihr ein gültiges Kommando zu machen.

In der obigen Abfrage wird zunächst ein Wert, das größte Konto, ermittelt, das irgendein Kunde hat. Dieser Betrag wird Teil des bedingten Ausdrucks 'konto = (...)'. Die Hauptabfrage wählt den Kunden aus, dessen Kontostand diese Bedingung erfüllt.

In der Abfrage ist es wichtig, daß die innere Abfrage nur einen Wert ergibt. Wenn sie mehrere Werte erzeugt, ist der bedingte Ausdruck 'konto = (mehr als ein Wert)' kein gültiger Ausdruck mehr. Im allgemeinen wählt die innere Abfrage eine Spalte aus; und in den meisten Fällen liefert sie dann nur eine Zeile dieser Spalte.

Es kommt manchmal vor, daß eine innere Abfrage Werte aus mehr als einer Zeile findet.

Das folgende Beispiel hat eine Bedingung mit dem Operator IN: Es findet alle Kunden und ihre Kontostände, die gleich den Kontoständen der Münchner Kunden sind. Weil eine Liste nach IN mehr als einen Wert enthalten darf, kann die innere, untergeordnete Abfrage mehr als einen Wert erzielen (aber aus ein und derselben Spalte).

SELECT knr, nachname, ort, konto
       FROM kunde
       WHERE konto IN
       (SELECT DISTINCT konto
               FROM kunde
               WHERE ort = 'München')

Die Anweisung

SELECT ort, FIXED (AVG(konto),7,2)
       FROM kunde
       GROUP BY ort
       HAVING AVG(konto) >= ALL
       (SELECT AVG(konto)
               FROM kunde
               GROUP BY ort)

hat als Ergebnis:

den Ort oder die Orte mit dem höchsten durchschnittlichen Kontostand. Das 'ALL' bedeutet, daß der gesuchte Ort einen durchschnittlichen Kontostand hat, der gleich oder größer ist als jeder andere durchschnittliche Kontostand, der von der inneren Frage gefunden wurde.

Die Anweisung

SELECT name, ort
       FROM hotel
       WHERE name = ANY
       (SELECT ort
               FROM hotel)

hat als Ergebnis:

eine Liste von Hotels (mit ihren Orten), die dieselben Namen haben wie irgendwelche Orte in der Basistabelle. Die innere Frage ermittelt die Ortsnamenliste, mit der die Hotelnamen verglichen werden.

Die Anweisung

SELECT * FROM kunde
       WHERE EXISTS
       (SELECT * FROM buchung
        WHERE kunde.knr = buchung.knr)

stellt die Bedingung:

Selektiere Kunden nur dann, wenn für sie eine oder mehrere Buchungen vorliegen.

Über die Kundennummer wird eine Verbindung zwischen den beiden Tabellen 'kunde' und 'buchung' hergestellt. Das Beispiel greift hiermit etwas der Beschreibung von Kapitel 6 voraus.

Man verwendet ALL oder ANY, wenn eine untergeordnete Frage entweder mehr als einen oder keinen Wert ergibt und wenn das in einer Bedingung berücksichtigt wird, die normalerweise genau einen Wert verlangt.

- 'WHERE wert = ALL(Ergebnis der Unterfrage)' ist wahr, wenn die Bedingung 'WHERE wert = Ergebnis' wahr ist für jedes Ergebnis, das von der Unterfrage gebildet wird. Andere Operationen statt '=' sind möglich. Ist eines der Ergebnisse NULL, dann ist das Ergebnis der Bedingung mit ALL unbekannt.

Das obige Beispiel, in dem ALL verwendet wird, hat als Ergebnis die Orte, deren durchschnittlicher Kontostand der größte durchschnittliche Kontostand ist.

- 'WHERE wert = ANY(Ergebnis der Unterfrage)' ist wahr, wenn die Bedingung 'WHERE wert = Ergebnis' wahr ist für irgendein Ergebnis, das von der Unterfrage gebildet wird.

Das obige Beispiel für den Gebrauch von ANY liefert Hotelnamen, die mit irgendeinem Ortsnamen übereinstimmen.

Man verwendet EXISTS, wenn die innere Frage nicht einen Wert ergeben muß, sondern nur herausfinden soll, ob eine Zeile existiert, die eine bestimmte Bedingung erfüllt.

Ermittle die durchschnittlichen Kontostände für alle Orte, in denen dieser Kontostand größer ist als das Durchschnittskonto für alle Kunden:

SELECT ort, FIXED (AVG(konto),7,2)
       FROM kunde
       GROUP BY ort
       HAVING AVG(konto) >
       (SELECT AVG(konto)
               FROM kunde)

Zeige alle Kunden, die eine Zimmerreservierung mit dem 12.04.1995 als Ankunftstag getätigt haben:

SELECT nachname
       FROM kunde
       WHERE knr IN
       (SELECT DISTINCT knr
               FROM buchung
	       WHERE ankunft = '12.04.1995')

Zeige einen Kunden dann, wenn er alle Buchungen ab einem vorgegebenen Datum getätigt hat.

SELECT knr, nachname
       FROM kunde
       WHERE knr = ALL
       (SELECT knr
               FROM buchung
               WHERE ankunft > '13.03.1996')

Es sind mehrere Stufen von untergeordneten Fragen möglich; d. h., man kann Anfragen auch inneren Anfragen unterordnen.

Ermittle alle Hotels in der Stadt, in der ein Kunde den höchsten Kontostand aller Kunden hat:

SELECT name, ort
       FROM hotel
       WHERE ort =
       (SELECT ort
               FROM kunde
               WHERE konto =
               (SELECT MAX(konto)
                       FROM kunde))


<< >> Up Title Contents Index