FirebirdSQL logo

IN

Verfügbar in

DSQL, PSQL, ESQL

Syntax
<value> [NOT] IN (<select_stmt> | <value_list>)

<value_list> ::= <value_1> [, <value_2> …]

Das Prädikat IN prüft, ob der Wert des Ausdrucks auf der linken Seite im Wertesatz der rechten Seite vorkommt.Der Wertesatz darf nicht mehr als 1500 Elemente enthalten.Das IN-Prädikat kann mit folgender äquivalenter Form ersetzt werden:

(<value> = <value_1> [OR <value> = <value_2> …])

<value> = { ANY | SOME } (<select_stmt>)

Wenn das Prädikat IN als Suchbedingung in DML-Abfragen verwendet wird, kann der Firebird-Optimizer einen Index auf die Suchspalte nutzen, sofern einer vorhanden ist.

In seiner zweiten Form prüft das Prädikat IN, ob der linke Ausdruckswert im Ergebnis der Unterabfrage vorhanden ist (oder nicht vorhanden, wenn NOT IN verwendet wird).

Die Unterabfrage darf nur eine Spalte abfragen, andernfalls wird es zum Fehler “count of column list and variable list do not match” kommen.

Abfragen, die das Prädikat IN mit einer Unterabfrage verwenden, können durch eine ähnliche Abfrage mittels des EXISTS-Prädikates ersetzt werden.Zum Beispiel folgende Abfrage:

SELECT
  model, speed, hd
FROM PC
WHERE
model IN (SELECT model
          FROM product
          WHERE maker = 'A');

kann ersetzt werden mittels EXISTS-Prädikat:

SELECT
  model, speed, hd
FROM PC
WHERE
 EXISTS (SELECT *
         FROM product
         WHERE maker = 'A'
           AND product.model = PC.model);

Jedoch gilt zu beachten, dass eine Abfrage mittels NOT IN und einer Unterabfrage nicht immer das gleiche Ergebnis zurückliefert wie sein Gegenpart mit NOT EXISTS.Dies liegt daran, dass EXISTS immer TRUE oder FALSE zurückgibt, wohingegen IN NULL in diesen beiden Fällen zurückliefert:

  1. wenn der geprüfte Wert NULL ist und die IN ()-Liste nicht leer ist

  2. wenn der geprüfte Wert keinen Treffer in der IN ()-Liste enthält und mindestens ein Element NULL ist.

Nur in diesen beiden Fällen wird IN () NULL zurückgeben, während das EXISTS-Prädikat FALSE zurückgibt ('keine passende Zeile gefunden', engl. 'no matching row found').In einer Suche oder, zum Beispiel in einem IF (…​)-Statement, bedeuten beide Ergebnisse einen “Fehler” und es macht damit keinen Unterschied.

Aber für die gleichen Daten gibt NOT IN () NULL zurück, während NOT EXISTS TRUE zurückgibt, was das Gegenteilige Ergebnis ist.

Schauen wir uns das folgendes Beispiel an:

-- Suche nach Bürgern die nicht am gleichen Tag wie eine
-- berühmte New Yorker Persönlichkeit geboren wurden
SELECT P1.name AS NAME
FROM Personnel P1
WHERE P1.birthday NOT IN (SELECT C1.birthday
                          FROM Celebrities C1
                          WHERE C1.birthcity = 'New York');

Nehmen wir nun an, dass die Liste der New Yorker Berühmtheiten nicht leer ist und mindestens einen NULL-Geburtstag aufweist.Dann gilt für alle Bürger, die nicht am gleichen Tag mit einer Berühmtheit Geburtstag haben, dass NOT IN NULL zurückgibt, da dies genau das ist was IN tut.Die Suchbedingung wurde nicht erfüllt und die Bürger werden nicht im Ergebnis des SELECT berücksichtigt, da die Aussage falsch ist.

Bürger, die am gleichen Tag wie eine Berühmtheit Geburtstag feiern, wird NOT IN korrekterweise FALSE zurückgeben, womit diese ebenfalls aussortiert werden, und damit keine Zeile zurückgegeben wird.

Wird die Form NOT EXISTS verwendet:

-- Suche nach Bürgern, die nicht am gleichen Tag wie eine
-- berühmte New Yorker Persönlichkeit geboren wurden
SELECT P1.name AS NAME
FROM Personnel P1
WHERE NOT EXISTS (SELECT *
                  FROM Celebrities C1
                  WHERE C1.birthcity = 'New York'
                    AND C1.birthday = P1.birthday);

nicht-Übereinstimmungen werden im NOT EXISTS-Ergebnis TRUE erhalten und ihre Datensätze landen im Rückgabesatz.

Tip

Wenn bei der Suche nach einer Nichtübereinstimmung die Möglichkeit besteht, dass NULL gefunden wird, sollten Sie NOT EXISTS verwenden.

Beispiele für die Verwendung
  1. Finde Mitarbeiter mit den Namen “Pete”, “Ann” und “Roger”:

    SELECT *
    FROM EMPLOYEE
    WHERE FIRST_NAME IN ('Pete', 'Ann', 'Roger');
  2. Finde alle Computer, die deren Hersteller mit dem Buchstaben “A” beginnt:

    SELECT
      model, speed, hd
    FROM PC
    WHERE
      model IN (SELECT model
                FROM product
                WHERE maker STARTING WITH 'A');
Siehe auch

EXISTS

SINGULAR

Verfügbar in

DSQL, PSQL, ESQL

Syntax
[NOT] SINGULAR (<select_stmt>)

Das Prädikat SINGULAR nimmt eine Unterabfrage als Argument und wertet sie als TRUE, wenn die Unterabfrage genau eine Ergebniszeile zurückgibt; andernfalls wird das Prädikat als FALSE ausgewertet.Die Unterabfrage kann mehrere Ausgabespalten auflisten, da die Zeilen sowieso nicht zurückgegeben werden.Sie werden nur auf (singuläre) Existenz geprüft.Der Kürze halber wird normalerweise ‘SELECT *’ angegeben.Das Prädikat SINGULAR kann nur zwei Werte zurückgeben: TRUE oder FALSE.

Beispiel

Finden Sie die Mitarbeiter, die nur ein Projekt haben.

SELECT *
FROM employee
WHERE SINGULAR(SELECT *
               FROM employee_project ep
               WHERE ep.emp_no = employee.emp_no)

docnext count = 3

Quantifizierte Unterabfrage-Prädikate

Ein Quantifizierer ist ein logischer Operator, der die Anzahl der Objekte festlegt, für die diese Behauptung wahr ist.Es ist keine numerische Größe, sondern eine logische, die die Behauptung mit dem vollen Satz möglicher Objekte verbindet.Solche Prädikate basieren auf logischen universellen und existentiellen Quantifizierern, die in der formalen Logik erkannt werden.

In Unterabfrageausdrücken ermöglichen quantifizierte Prädikate den Vergleich einzelner Werte mit den Ergebnissen von Unterabfragen;sie haben die folgende gemeinsame Form:

<value expression> <comparison operator> <quantifier> <subquery>

ALL

Verfügbar in

DSQL, PSQL, ESQL

Syntax
<value> <op> ALL (<select_stmt>)

Wenn der ALL-Quantifizierer verwendet wird, ist das Prädikat TRUE, wenn jeder Wert, der von der Unterabfrage zurückgegeben wird, die Bedingung des Prädikates in der Hauptabfrage erfüllt ist.

Beispiel

Zeige nur jene Kunden an, deren Bewertungen höher sind als die Bewertung jedes Kunden in Paris.

SELECT c1.*
FROM Customers c1
WHERE c1.rating > ALL
      (SELECT c2.rating
       FROM Customers c2
       WHERE c2.city = 'Paris')
Important

Wenn die Unterabfrage einen leeren Satz zurückgibt, ist das Prädikat TRUE für jeden linken Wert, unabhängig vom Operator.Dies mag widersprüchlich erscheinen, denn jeder linke Wert wird gegenüber dem rechten betrachtet als: kleiner als, größer als, gleich sowie ungleich.

Dennoch passt dies perfekt in die formale Logik: Wenn der Satz leer ist, ist das Prädikat 0 mal wahr, d.h. für jede Zeile im Satz.

ANY and SOME

Verfügbar in

DSQL, PSQL, ESQL

Syntax
<value> <op> {ANY | SOME} (<select_stmt>)

Die Quantifizierer ANY und SOME sind in ihrem Verhalten identisch.Offensichtlich sind beide im SQL-Standard vorhanden, so dass sie austauschbar verwendet werden können, um die Lesbarkeit der Operatoren zu verbessern.Wird der ANY- oder SOME-Quantifizierer verwendet, ist das Prädikat TRUE, wenn einer der zurückgegebenen Werte der Unterabfrage die Suchbedingung der Hauptabfrage erfüllt.Gibt die Unterabfrage keine Zeile zurück, wird das Prädikat automtisch als FALSE angesehen.

Beispiel

Zeige nur die Kunden, deren Bewertungen höher sind als die eines oder mehrerer Kunden in Rom.

SELECT *
FROM Customers
WHERE rating > ANY
      (SELECT rating
       FROM Customers
       WHERE city = 'Rome')