Kategorien:

Abfragesyntax

WHERE

Die WHERE-Klausel gibt eine Bedingung an, die als Filter fungiert. Sie können die WHERE-Klausel für folgende Aufgaben verwenden:

  • Filtern des Ergebnisses der FROM-Klausel einer SELECT-Anweisung

  • Angeben, auf welchen Zeilen UPDATE, MERGE oder DELETE ausgeführt werden sollen

Syntax

...
WHERE <predicate>
[ ... ]
Copy
predicate

Ein boolescher Ausdruck. Der Ausdruck kann logische Operatoren enthalten, beispielsweise AND, OR und NOT.

Nutzungshinweise

  • Prädikate in der WHERE-Klausel verhalten sich so, als würden sie nach der FROM-Klausel ausgewertet werden (auch wenn das Optimierungsprogramm Prädikate neu anordnen kann, wenn das keine Auswirkungen auf die Ergebnisse hat). Wenn beispielsweise ein Prädikat in der WHERE-Klausel auf Spalten einer Tabelle verweist, die Teil einer äußeren Verknüpfung in der FROM-Klausel ist, operiert der Filter auf den von der Verknüpfung zurückgegebenen Zeilen (die mit NULL-Werten aufgefüllt sein können).

  • Gehen Sie bei der Erstellung von Ausdrücken, die NULL-Werte auswerten können, mit großer Sorgfalt vor.

    • In den meisten Kontexten gibt der boolesche Ausdruck NULL = NULL den Wert NULL zurück und nicht TRUE. Erwägen Sie die Verwendung von IS [ NOT ] NULL, um NULL-Werte zu vergleichen.

    • Wenn in einer WHERE-Klausel ein Ausdruck NULL ergibt, wird die Zeile für diesen Ausdruck aus dem Resultset entfernt (d. h. sie wird herausgefiltert).

  • Die maximale Anzahl von Ausdrücken in einer Liste ist 16.384. Die Begrenzung gilt zum Beispiel für die Anzahl der Ausdrücke in der folgenden SELECT-Anweisung:

    SELECT column_x
       FROM mytable
       WHERE column_y IN (<expr1>, <expr2>, <expr3> ...);
    
    Copy

    Um das Erreichen des Limits zu vermeiden, führen Sie eine Join-Verknüpfung mit einer Lookup-Tabelle aus, die die Werte des Ausdrucks enthält, anstatt die Werte mit einer IN-Klausel anzugeben. Wenn beispielsweise die Ausdruckswerte aus dem vorherigen Beispiel zu einer Lookup-Tabelle namens mylookuptable hinzugefügt werden, können Sie die folgende Abfrage erfolgreich ausführen, selbst wenn die Lookup-Tabelle mehr als 16.384 Zeilen aufweist:

    SELECT column_x
      FROM mytable t
      JOIN mylookuptable l
      ON t.column_y = l.values_for_comparison;
    
    Copy

Verknüpfungen in der WHERE-Klausel

Obwohl die WHERE-Klausel in erster Linie der Filterung dient, kann die WHERE-Klausel auch verwendet werden, um viele Typen von JOIN-Verknüpfungen auszudrücken. Allgemeine Informationen zum JOIN-Konzept finden Sie unter Verwenden von Verknüpfungen (Joins).

Eine WHERE-Klausel kann eine Verknüpfung spezifizieren, indem sie JOIN-Bedingungen enthält, d. h. boolesche Ausdrücke, die definieren, welche Zeilen von einer Seite des JOIN mit welchen Zeilen der anderen Seite des JOIN übereinstimmen.

Die beiden folgenden äquivalenten Abfragen zeigen, wie sich eine innere Verknüpfung in der WHERE- oder FROM-Klausel ausdrücken lässt:

SELECT t1.c1, t2.c2
    FROM t1, t2
    WHERE t1.c1 = t2.c2;

SELECT t1.c1, t2.c2
    FROM t1 INNER JOIN t2
        ON t1.c1 = t2.c2;
Copy

Äußere Verknüpfungen können in der WHERE-Klausel mit der (+)-Syntax und in der FROM-Klausel mit den Schlüsselwörtern OUTER JOIN angegeben werden.

Wenn Sie eine äußere Verknüpfung mit (+) angeben, wendet die WHERE-Klausel die (+)-Syntax auf jede Verknüpfungsspalte der Tabelle an, die „innen“ ist (wie unten definiert).

Bemerkung

Das Ergebnis einer äußeren Verknüpfung enthält eine Kopie aller Zeilen einer Tabelle. Unter diesem Thema wird die Tabelle, deren Zeilen erhalten bleiben, als „äußere“ Tabelle und die andere Tabelle als „innere“ Tabelle bezeichnet.

  • In einem LEFT OUTER JOIN ist die linke Tabelle die äußere Tabelle und die rechte Tabelle die innere Tabelle.

  • In einem RIGHT OUTER JOIN ist die rechte Tabelle die äußere Tabelle und die linke Tabelle die innere Tabelle.

Die folgenden Abfragen enthalten äquivalente linke äußere Verknüpfungen, von denen eine den JOIN in der FROM-Klausel und die andere den JOIN in der WHERE-Klausel angibt:

SELECT t1.c1, t2.c2
FROM t1 LEFT OUTER JOIN t2
        ON t1.c1 = t2.c2;

SELECT t1.c1, t2.c2
FROM t1, t2
WHERE t1.c1 = t2.c2(+);
Copy

In der zweiten Abfrage steht (+) auf der rechten Seite und identifiziert die innere Tabelle.

Nachfolgend finden Sie eine Beispielausgabe für beide Abfragen:

+-------+-------+
| T1.C1 | T2.C2 |
|-------+-------|
|     1 |     1 |
|     2 |  NULL |
|     3 |     3 |
|     4 |  NULL |
+-------+-------+
Copy

Wenn Sie eine Tabelle über mehrere Spalten verknüpfen, verwenden Sie die Notation (+) für jede Spalte in der inneren Tabelle (t2 im folgenden Beispiel):

SELECT t1.c1, t2.c2
FROM t1, t2
WHERE t1.c1 = t2.c2 (+)
  AND t1.c3 = t2.c4 (+);
Copy

Bemerkung

Es gibt viele Einschränkungen hinsichtlich der Frage, wo die (+)-Syntax verwendet werden darf. Äußere Verknüpfungen der FROM-Klausel sind auch aussagekräftiger. Snowflake empfiehlt, die Notation (+) nur zum Portieren von Code zu verwenden, der diese Notation bereits nutzt. Bei neuem Code sollten Sie diese Notation vermeiden.

Folgende Einschränkungen bestehen:

  • Die (+)-Notation kann nicht zum Erstellen von FULL OUTER JOIN verwendet werden. Es können lediglich LEFT OUTER JOIN und RIGHT OUTER JOIN erstellt werden. Folgendes ist beispielsweise nicht gültig. Die Anweisung führt zu folgender Fehlermeldung: SQL compilation error: Outer join predicates form a cycle between 'T1' and 'T2'.

    -- NOT VALID
    select t1.c1
        from t1, t2
        where t1.c1 (+) = t2.c2 (+);
    
    Copy
  • Wenn eine Tabelle in einer Abfrage an mehreren Verknüpfung beteiligt ist, kann die (+)-Notation die Tabelle in nur einer dieser Verknüpfungen als innere Tabelle angeben. Das Folgende ist nicht gültig, weil t1 als innere Tabelle in zwei Verknüpfungen dient. Die Anweisung führt zu folgender Fehlermeldung: SQL compilation error: Table 'T1' is outer joined to multiple tables: 'T3' and 'T2'.

    -- NOT VALID
    select t1.c1
        from t1, t2, t3
        where t1.c1 (+) = t2.c2
          and t1.c1 (+) = t3.c3;
    
    Copy

    Beachten Sie jedoch, dass Sie (+) verwenden können, um unterschiedliche Tabellen als innere Tabellen in verschiedenen Verknüpfungen derselben SQL-Anweisung zu identifizieren. Das folgende Beispiel verknüpft drei Tabellen: t1, t2 und t3, von denen zwei innere Tabellen sind (in verschiedenen Verknüpfungen). Diese Anweisung führt Folgendes aus:

    • Ein LEFT OUTER JOIN zwischen t1 und t2 (wobei t2 die innere Tabelle ist).

    • Ein LEFT OUTER JOIN zwischen t2 und t3 (wobei t3 die innere Tabelle ist).

    select t1.c1
        from t1, t2, t3
        where t1.c1 = t2.c2 (+)
          and t2.c2 = t3.c3 (+);
    
    Copy

Das (+) kann unmittelbar neben dem Tabellen- und Spaltennamen stehen oder durch Leerzeichen getrennt sein. Die beiden folgenden Varianten sind gültig:

where t1.c1 = t2.c2(+)

where t1.c1 = t2.c2 (+)
Copy

Eine Abfrage kann Verknüpfungen enthalten, die sowohl in der FROM ... ON ...-Klausel als auch in der WHERE-Klausel angegeben sind. Die Angabe von Verknüpfungen in verschiedenen Klauseln derselben Abfrage kann jedoch die Lesbarkeit dieser Abfrage erschweren.

Die Unterstützung von Verknüpfungen in der WHERE-Klausel dient in erster Linie der Abwärtskompatibilität mit älteren Abfragen, die nicht die FROM ... ON ...-Syntax verwenden. Snowflake empfiehlt beim Schreiben neuer Abfragen mit Verknüpfungen die Verwendung von FROM ... ON .... Weitere Details dazu finden Sie unter JOIN.

Beispiele

Einfache Beispiele für Filterung

Im Folgenden werden einige einfache Anwendungen der WHERE-Klausel veranschaulicht:

SELECT * FROM invoices
  WHERE invoice_date < '2018-01-01';

SELECT * FROM invoices
  WHERE invoice_date < '2018-01-01'
    AND paid = FALSE;
Copy

In diesem Beispiel wird eine Unterabfrage verwendet, um alle Rechnungen anzuzeigen, deren Rechnungsbeträge unter dem Durchschnitt liegen:

SELECT * FROM invoices
    WHERE amount < (
                   SELECT AVG(amount)
                       FROM invoices
                   )
    ;
Copy

Ausführen von Verknüpfungen mit der WHERE-Klausel

Um eine Verknüpfung in der WHERE-Klausel anzugeben, listen Sie die zu verknüpfenden Tabellen in der FROM clause auf, wobei Sie die Tabellen durch ein Komma trennen. Geben Sie die Verknüpfungsbedingung als Filter in der WHERE-Klausel an, wie im folgenden Beispiel gezeigt:

SELECT t1.col1, t2.col1
    FROM t1, t2
    WHERE t2.col1 = t1.col1
    ORDER BY 1, 2;
+------+------+
| COL1 | COL1 |
|------+------|
|    2 |    2 |
|    2 |    2 |
|    3 |    3 |
+------+------+
Copy

Bemerkung

Der Kommaoperator ist ältere Syntax für INNER JOIN. Die folgende Anweisung zeigt die empfohlene Art und Weise, eine Verknüpfung mit neuerer Syntax auszuführen. Die folgende Abfrage entspricht der obigen Abfrage:

SELECT t1.col1, t2.col1
    FROM t1 JOIN t2
        ON t2.col1 = t1.col1
    ORDER BY 1, 2;
+------+------+
| COL1 | COL1 |
|------+------|
|    2 |    2 |
|    2 |    2 |
|    3 |    3 |
+------+------+
Copy

Im nächsten Abschnitt werden Verknüpfungen über drei Tabellen gezeigt und der Unterschied im Verhalten bei Verwendung von keinem, einem oder zwei (+)-Operatoren für äußere Verknüpfungen.

Bevor Sie die Abfragen ausführen, erstellen und laden Sie die Tabellen, die in den Verknüpfungen verwendet werden sollen:

create table departments (
    department_ID INTEGER,
    department_name VARCHAR,
    location VARCHAR
    );
insert into departments (department_id, department_name, location) values
    (10, 'CUSTOMER SUPPORT', 'CHICAGO'),
    (40, 'RESEARCH', 'BOSTON'),
    (80, 'Department with no employees yet', 'CHICAGO'),
    (90, 'Department with no projects or employees yet', 'EREHWON')
    ;

create table projects (
    project_id integer,
    project_name varchar,
    department_id integer
    );
insert into projects (project_id, project_name, department_id) values
    (4000, 'Detect fake product reviews', 40),
    (4001, 'Detect false insurance claims', 10),
    (9000, 'Project with no employees yet', 80),
    (9099, 'Project with no department or employees yet', NULL)
    ;

create table employees (
    employee_ID INTEGER,
    employee_name VARCHAR,
    department_id INTEGER,
    project_id INTEGER
    );
insert into employees (employee_id, employee_name, department_id, project_id)
  values
    (1012, 'May Aidez', 10, NULL),
    (1040, 'Devi Nobel', 40, 4000),
    (1041, 'Alfred Mendeleev', 40, 4001)
    ;
Copy

Führen Sie eine dreifache innere Verknüpfung aus. Dabei wird nicht (+) (oder das Schlüsselwort OUTER) verwendet, sodass es sich um eine innere Verknüpfung handelt. Die Ausgabe enthält nur Zeilen, für die es eine Abteilung, ein Projekt und einen Mitarbeiter gibt:

SELECT d.department_name, p.project_name, e.employee_name
    FROM  departments d, projects p, employees e
    WHERE
            p.department_id = d.department_id
        AND
            e.project_id = p.project_id
    ORDER BY d.department_id, p.project_id, e.employee_id;
+------------------+-------------------------------+------------------+
| DEPARTMENT_NAME  | PROJECT_NAME                  | EMPLOYEE_NAME    |
|------------------+-------------------------------+------------------|
| CUSTOMER SUPPORT | Detect false insurance claims | Alfred Mendeleev |
| RESEARCH         | Detect fake product reviews   | Devi Nobel       |
+------------------+-------------------------------+------------------+
Copy

Führen Sie eine äußere Verknüpfung aus. Dies ähnelt der vorhergehenden Anweisung mit Ausnahme, dass hier (+) verwendet wird, um die zweite Verknüpfung zu einer rechten äußeren Verknüpfung zu machen. Das ergibt folgenden Effekt: Wenn eine Abteilung in der Ausgabe enthalten ist, dann sind alle Projekte dieser Abteilung enthalten, auch wenn diese Projekte keine Mitarbeiter haben:

SELECT d.department_name, p.project_name, e.employee_name
    FROM  departments d, projects p, employees e
    WHERE
            p.department_id = d.department_id
        AND
            e.project_id(+) = p.project_id
    ORDER BY d.department_id, p.project_id, e.employee_id;
+----------------------------------+-------------------------------+------------------+
| DEPARTMENT_NAME                  | PROJECT_NAME                  | EMPLOYEE_NAME    |
|----------------------------------+-------------------------------+------------------|
| CUSTOMER SUPPORT                 | Detect false insurance claims | Alfred Mendeleev |
| RESEARCH                         | Detect fake product reviews   | Devi Nobel       |
| Department with no employees yet | Project with no employees yet | NULL             |
+----------------------------------+-------------------------------+------------------+
Copy

Führen Sie zwei äußere Verknüpfungen durch. Dies ähnelt der vorhergehenden Anweisung mit Ausnahme, dass hier (+) verwendet wird, um beide Verknüpfungen zu inneren Verknüpfungen zu machen. Der Effekt ist, dass alle Abteilungen einbezogen werden (auch wenn sie noch keine Projekte oder Mitarbeiter haben) und alle Projekte, die mit den Abteilungen verbunden sind (auch wenn sie noch keine Mitarbeiter haben). Beachten Sie, dass die Ausgabe Projekte ausschließt, die keine Abteilung haben.

SELECT d.department_name, p.project_name, e.employee_name
    FROM  departments d, projects p, employees e
    WHERE
            p.department_id(+) = d.department_id
        AND
            e.project_id(+) = p.project_id
    ORDER BY d.department_id, p.project_id, e.employee_id;
+----------------------------------------------+-------------------------------+------------------+
| DEPARTMENT_NAME                              | PROJECT_NAME                  | EMPLOYEE_NAME    |
|----------------------------------------------+-------------------------------+------------------|
| CUSTOMER SUPPORT                             | Detect false insurance claims | Alfred Mendeleev |
| RESEARCH                                     | Detect fake product reviews   | Devi Nobel       |
| Department with no employees yet             | Project with no employees yet | NULL             |
| Department with no projects or employees yet | NULL                          | NULL             |
+----------------------------------------------+-------------------------------+------------------+
Copy

(Denken Sie jedoch daran, dass Snowflake empfiehlt, das Schlüsselwort OUTER in der FROM-Klausel zu verwenden, anstatt den Operator (+) in der WHERE-Klausel).