Show TOC Anfang des Inhaltsbereichs

Subqueries  Dokument im Navigationsbaum lokalisieren

Eine Subquery ist eine spezielle SELECT-Anweisung, die innerhalb bestimmter Bedingungen der WHERE- oder HAVING-Klauseln für eine Unterabfrage verwendet werden kann. Subqueries können aber nicht in der ON-Bedingung der FROM-Klausel verwendet werden. Die Syntax für eine Subquery ist:

( SELECT      result
    FROM      source
    [WHERE    condition]
    [GROUP BY fields]
    [HAVING   cond]       )

Es steht also eine etwas eingeschränkte Funktionalität der vollständigen SELECT-Anweisung zu Verfügung, da es keine INTO- oder ORDER-BY-Klauseln gibt.

Subqueries sind schachtelbar, d.h. in den WHERE- und HAVING-Klauseln einer Subquery kann wieder eine Subquery verwendet werden. Wenn eine geschachtelte Subquery in ihrer WHERE-Klausel dabei Felder der darüberliegenden Abfrage verwendet, spricht man von einer korrelierten Subquery. Dann wird die Subquery einzeln für jede Zeile der Datenbanktabelle ausgewertet, welche die darüberliegende Abfrage erfüllt.

Skalare Subqueries

Bei einer skalaren Subquery ist die Selektion der SELECT-Klausel auf eine Spalte oder einen Aggregatausdruck beschränkt. Der Ausdruck result der SELECT-Klausel ist also

... line [agg] s

Bei der Spaltenangabe der SELECT-Klausel ist nur ein einziger Feldbezeichner möglich.

Subqueries in Bedingungen

Eine nicht skalare Subquery kann nur in der Bedingung

... [NOT] EXISTS subquery...

einer WHERE- oder HAVING-Klausel verwendet werden. Die Bedingung ist wahr, wenn die Selektion der Subquery mindestens eine [keine] Zeile enthält.

Skalare Subqueries in Bedingungen

Neben der Verwendung in obiger Bedingung kann eine skalare Subquery in weiteren Bedingungen verwendet werden.

Überprüfung eines Werts der Subquery

Eine mögliche Bedingung mit skalaren Subqueries ist:

... s [NOT] IN subquery...

Diese Bedingung ist wahr, falls der Wert von s [nicht] in der Ergebnismenge der skalaren Subquery subquery enthalten ist.

Skalare Subqueries in Vergleichen

Die anderen Bedingungen können alle Vergleiche sein, deren Operatoren in der Tabelle für Vergleiche mit allen Typen in der WHERE-Klausel stehen. Dabei ist zu unterscheiden, ob die Selektion der Subquery eine oder mehrere Zeilen enthält.

Einzeilige Subquery

Enthält die Selektion der Subquery nur eine Zeile, schreibt man für den Vergleich:

... s operator subquery...

Es wird der Wert von s mit dem Wert in der Selektion der Subquery verglichen und die Bedingung ist entsprechend wahr oder falsch.

Die Subquery muss einzeilig sein, ansonsten kommt es zu einem Laufzeitfehler. Eine einzeilige Subquery kann durch die vollständige Angabe des Schlüssels in der WHERE-Klausel erzeugt werden.

Mehrzeilige Subquery

Enthält die Selektion der Subquery mehrere Zeilen, muss man den Vergleich wie folgt schreiben:

... s operator ALL|ANY|SOME subquery...

Mit dem Vorsatz ALL vor der Subquery ist die Bedingung nur wahr, falls der Vergleich für alle Zeilen der Subquery wahr ist. Mit dem Zusatz ANY oder SOME vor der Subquery ist die Bedingung wahr, falls der Vergleich für mindestens eine der Zeilen der Subquery wahr ist. Der Gleichheitsoperator (= oder EQ) in Verbindung mit ANY oder SOME wirkt also wie obiger Operator INzu Überprüfung eines Werts.

Falls die Selektion einer Subquery mehrere Zeilen enthält und es ist keiner der Ausdrücke ALL, ANY oder SOME aufgeführt, kommt es zu einem Laufzeitfehler.

Beispiel

Korrelierte nicht skalare Subquery.

REPORT demo_select_subquery_1.

DATA: name_tab TYPE TABLE OF scarr-carrname,
      name  LIKE LINE OF name_tab.

SELECT  carrname
  INTO  TABLE name_tab
  FROM  scarr
  WHERE EXISTS ( select  *
                   FROM  spfli
                   WHERE carrid   =  scarr~carrid AND
                         cityfrom = '
NEW YORK'        ).

LOOP AT name_tab INTO name.
  
WRITE: / name.
ENDLOOP.

Es werden alle Zeilen der Datenbanktabelle SCARR selektiert, deren Fluggesellschaften von NEW YORK aus fliegen.

Beispiel

Skalare Subquery.

REPORT demo_select_subquery_2.

DATA: carr_id TYPE spfli-carrid VALUE 'LH',
      conn_id TYPE spfli-connid VALUE '0400'.

DATA: city  TYPE sgeocity-city,
      lati  TYPE p DECIMALS 2,
      longi TYPE p DECIMALS 2.

SELECT  SINGLE city latitude longitude
  INTO  (city, lati, longi)
  FROM  sgeocity
  WHERE city IN ( select  cityfrom
                    FROM  spfli
                    WHERE carrid = carr_id AND
                          connid = conn_id      ).

WRITE: city, lati, longi.

Es werden die geographische Breite und Länge der Abflugstadt des Flugs LH 402 aus der Datenbanktabelle SGEOCITY selektiert.

Beispiel

Skalare Subquery.

REPORT demo_select_subquery_3.

DATA: wa TYPE sflight,
      plane LIKE wa-planetype,
      seats LIKE wa-seatsmax.

SELECT     carrid connid planetype seatsmax MAX( seatsocc )
  INTO     (wa-carrid, wa-connid, wa-planetype,
            wa-seatsmax, wa-seatsocc)
  FROM     sflight
  GROUP BY carrid connid planetype seatsmax
  ORDER BY carrid connid.

  WRITE: /  wa-carrid,
            wa-connid,
            wa-planetype,
            wa-seatsmax,
            wa-seatsocc.

  HIDE: wa-carrid, wa-connid, wa-seatsmax.

ENDSELECT.

AT LINE-SELECTION.

  WINDOW STARTING AT 45 3 ENDING AT 85 13.

  WRITE: 'Alternative Plane Types',
         'for', wa-carrid, wa-connid.

  ULINE.

  SELECT  planetype seatsmax
    INTO  (plane, seats)
    FROM  saplane AS plane
    WHERE seatsmax < wa-seatsmax AND
          seatsmax >= ALL ( select  seatsocc
                              FROM  sflight
                              WHERE carrid = wa-carrid AND
                                    connid = wa-connid     )
    ORDER BY seatsmax.

    WRITE: / plane, seats.

  ENDSELECT.

Die Listenausgabe ist nach einem Doppelklick auf eine Zeile:

Diese Grafik wird im zugehörigen Text erklärt

Auf der Verzeigungsliste werden alle Flugzeugtypen angezeigt, die für eine Verbindung beim derzeitigen Buchungsstand für alle Flüge genügend aber weniger Sitzplätze haben als der aktuelle Flugzeugtyp.

 

 

Ende des Inhaltsbereichs