- カテゴリ:
WHERE¶
WHERE
句は、フィルターとして機能する条件を指定します。 WHERE
句を使用して次のことができます。
使用上の注意¶
WHERE 句の述語は、 FROM 句の後に評価されるかのように動作します(ただし、結果に影響しない場合、オプティマイザーは述語を並べ替えることができます)。例えば、WHERE 句の述語が FROM 句の外部結合に参加しているテーブルの列を参照する場合、結合から返された行(NULLs が埋め込まれる可能性があります)をフィルターが操作します。
NULLs を評価する可能性のある式を作成するときは注意してください。
ほとんどの場合、ブール式
NULL = NULL
は TRUE ではなく NULL を返します。 IS [ NOT ] NULL を使用して NULL 値を比較することを検討してください。WHERE
句で、式が NULL と評価された場合、その式の行は結果セットから削除されます(つまり、フィルターで除外されます)。
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;
外部結合は、 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(+);
2番目のクエリでは、 (+)
が右側にあり、内部テーブルを識別します。
両方のクエリの出力例を以下に示します。
+-------+-------+ | T1.C1 | T2.C2 | |-------+-------| | 1 | 1 | | 2 | NULL | | 3 | 3 | | 4 | NULL | +-------+-------+
複数の列でテーブルを結合する場合は、内部テーブルの 各 列で (+)
表記を使用します(以下の例では t2
)。
SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+) AND t1.c3 = t2.c4 (+);注釈
(+)
注釈を表示できる場所には多くの制限があります。 FROM 句の外部結合のほうが表現性に優れています。Snowflakeは、既にその表記法を使用しているコードを移植する場合にのみ(+)
表記法を使用することを推奨しています。新しいコードではその表記を避ける必要があります。制限事項は次のとおりです。
FULL OUTER JOIN
を作成するために(+)
表記を使用することはできません。作成できるのはLEFT OUTER JOIN
とRIGHT 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 (+);テーブルがクエリの複数の結合に参加している場合、
(+)
表記では、それらの結合の 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;ただし、
(+)
を使用して、同じ SQL ステートメントの 異なる結合 の内部テーブルとして 異なるテーブル を識別することはできます。次の例では、t1
、t2
、およびt3
の3つのテーブルを結合します。そのうちの2つは、(異なる結合の)内部テーブルです。このステートメントは次を実行します。
t1
とt2
の間の LEFT OUTER JOIN(t2
は内部テーブル)。
t2
とt3
の間の LEFT OUTER JOIN(t3
は内部テーブル)。select t1.c1 from t1, t2, t3 where t1.c1 = t2.c2 (+) and t2.c2 = t3.c3 (+);
(+)
は、テーブルと列の名前のすぐ隣にある場合もあれば、空白で区切られている場合もあります。次のいずれも有効です。
where t1.c1 = t2.c2(+) where t1.c1 = t2.c2 (+)
クエリには、 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;
この例では、サブクエリを使用して、請求額が平均を下回るすべての請求書を表示します。
SELECT * FROM invoices WHERE amount < ( SELECT AVG(amount) FROM invoices ) ;
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 | +------+------+
注釈
カンマ演算子は、 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 | +------+------+
この次のセクションでは、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) ;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 | +------------------+-------------------------------+------------------+外部結合を実行します。これは、
(+)
を使用して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 | +----------------------------------+-------------------------------+------------------+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 | +----------------------------------------------+-------------------------------+------------------+
(ただし、Snowflake では、 WHERE
句で (+)
演算子を使用するのではなく、 FROM
句で OUTER
キーワードを使用することをお勧めします。)