カテゴリ:

クエリ構文

WHERE

WHERE 句は、フィルターとして機能する条件を指定します。 WHERE 句を使用して次のことができます。

  • SELECT ステートメントの FROM 句の結果をフィルタリングします。

  • UPDATEMERGE、または DELETE で操作する行を指定します。

構文

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

ブール式。式には、 ANDORNOT などの 論理演算子 を含めることができます。

使用上の注意

  • WHERE 句の述語は、 FROM 句の後に評価されるかのように動作します(ただし、結果に影響しない場合、オプティマイザーは述語を並べ替えることができます)。例えば、WHERE 句の述語が FROM 句の外部結合に参加しているテーブルの列を参照する場合、結合から返された行(NULLs が埋め込まれる可能性があります)をフィルターが操作します。

  • NULLs を評価する可能性のある式を作成するときは注意してください。

    • ほとんどの場合、ブール式 NULL = NULL は TRUE ではなく NULL を返します。 IS [ NOT ] NULL を使用して NULL 値を比較することを検討してください。

    • WHERE 句で、式が NULL と評価された場合、その式の行は結果セットから削除されます(つまり、フィルターで除外されます)。

  • リスト内の式の最大数は16,384です。たとえば、制限は次の SELECT ステートメントの式の数に適用されます。

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

    制限に達しないようにするには、 IN 句を使用して値を指定するのではなく、式値を含むルックアップテーブルで結合を実行します。たとえば、前述の例の式値が mylookuptable という名前のルックアップテーブルに追加されている場合は、ルックアップテーブルに16,384行以上あっても、以下のクエリを正常に実行することができます。

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

WHERE 句で結合します

WHERE 句は主にフィルタリング用ですが、 WHERE 句を使用してさまざまな種類の結合を表現することもできます。結合の概念については、 JOIN(結合)の操作 をご参照ください。

WHERE 句は、結合条件を含めることで結合を指定できます。結合条件は、 JOIN の一方の側のどの行が結合のもう一方の側の行と一致するかを定義するブール式です。

次に挙げる2つの同義のクエリは、 WHERE または FROM 句で結合を表現する方法を示しています。

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

外部結合は、 WHERE 句の (+) 構文または FROM 句の OUTER JOIN キーワードのいずれかを使用して指定できます。

(+) で外部結合を指定すると、 WHERE 句は「内部」(以下で定義)であるテーブルの各結合列に (+) を適用します。

注釈

外部結合の結果には、1つのテーブルからの行すべてのコピーが含まれます。このトピックでは、行が保持されているテーブルを「外部」テーブルと呼び、もう一方のテーブルを「内部」テーブルと呼びます。

  • LEFT OUTER JOIN では、左側のテーブルが外側のテーブルで、右側のテーブルが内側のテーブルです。

  • RIGHT OUTER JOIN では、右側のテーブルが外側のテーブルで、左側のテーブルが内側のテーブルです。

次のクエリは、同等の左外部結合を示しています。そのうちの1つは、 FROM 句の結合を指定し、もう1つは WHERE 句の結合を指定します。

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

2番目のクエリでは、 (+) が右側にあり、内部テーブルを識別します。

両方のクエリの出力例を以下に示します。

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

複数の列でテーブルを結合する場合は、内部テーブルの 列で (+) 表記を使用します(以下の例では t2)。

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

注釈

(+) 注釈を表示できる場所には多くの制限があります。 FROM 句の外部結合のほうが表現性に優れています。Snowflakeは、既にその表記法を使用しているコードを移植する場合にのみ (+) 表記法を使用することを推奨しています。新しいコードではその表記を避ける必要があります。

制限事項は次のとおりです。

  • FULL OUTER JOIN を作成するために (+) 表記を使用することはできません。作成できるのは LEFT OUTER JOINRIGHT OUTER JOIN のみです。次はサポートされて いません。このステートメントにより、次のエラーメッセージが表示されます。 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
  • テーブルがクエリの複数の結合に参加している場合、 (+) 表記では、それらの結合の 1つ でのみテーブルを内部テーブルとして指定できます。 t1 は2つの結合で内部テーブルとして機能するため、以下は 無効 です。このステートメントにより、次のエラーメッセージが表示されます。 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

    ただし、 (+) を使用して、同じ SQL ステートメントの 異なる結合 の内部テーブルとして 異なるテーブル を識別することはできます。次の例では、 t1t2、および t3 の3つのテーブルを結合します。そのうちの2つは、(異なる結合の)内部テーブルです。このステートメントは次を実行します。

    • t1t2 の間の LEFT OUTER JOIN(t2 は内部テーブル)。

    • t2t3 の間の LEFT OUTER JOIN(t3 は内部テーブル)。

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

(+) は、テーブルと列の名前のすぐ隣にある場合もあれば、空白で区切られている場合もあります。次のいずれも有効です。

where t1.c1 = t2.c2(+)

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

クエリには、 FROM ... ON ... 句と WHERE 句の両方で指定された結合を含めることができます。ただし、同じクエリの異なる句で結合を指定すると、そのクエリが読みにくくなる可能性があります。

WHERE 句での結合のサポートは、主に FROM ... ON ... 構文を使用しない古いクエリとの下位互換性のためです。Snowflakeは、結合を使用して新しいクエリを作成するときに FROM ... ON ... を使用することをお勧めします。詳細については、 JOIN をご参照ください。

フィルタリングの簡単な例

以下に、 WHERE 句の簡単な使用例を示します。

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

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

この例では、サブクエリを使用して、請求額が平均を下回るすべての請求書を表示します。

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

WHERE 句での結合の実行

WHERE 句で結合を指定するには、結合するテーブルを FROM clause でリストし、テーブルをコンマで区切ります。次の例に示すように、 WHERE 句で結合条件をフィルターとして指定します。

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

注釈

カンマ演算子は、 INNER JOIN の古い構文です。次のステートメントは、新しい構文を使用して結合を実行するための推奨される方法を示しています。以下のクエリは、上記のクエリと同等です。

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

この次のセクションでは、3-テーブル結合を示し、0、1、または 2 (+) 外部結合演算子との動作の違いを示します。

クエリを実行する前に、結合で使用するテーブルを作成してロードします。

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

3方向の内部結合を実行します。これは (+) (または OUTER キーワード)を使用しないため、内部結合です。出力には、部門、プロジェクト、および従業員が存在する行のみが含まれます。

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

外部結合を実行します。これは、 (+) を使用して2番目の結合を右側に外部結合することを 除き、前述のステートメントに似ています。その結果、ある部門が出力に含まれている場合、それらのプロジェクトに従業員がいない場合でも、その部門のすべてのプロジェクトが含まれます。

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

2 つの外部結合を実行します。これは、前のステートメント を除いて と同じですが、これは (+) を使用して両方の結合を外部結合にします。その結果、(プロジェクトまたは従業員がまだいない場合でも)すべての部門が含まれ、(まだ従業員がいない場合でも)部門に関連付けられているすべてのプロジェクトが含まれます。出力には、部門のないプロジェクトが含まれていないことに注意してください。

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

(ただし、Snowflake では、 WHERE 句で (+) 演算子を使用するのではなく、 FROM 句で OUTER キーワードを使用することをお勧めします。)