- Catégories :
WHERE¶
La clause WHERE
spécifie une condition qui agit comme un filtre. Vous pouvez utiliser la clause WHERE
pour :
Filtrer le résultat de la clause FROM dans une instruction SELECT.
Préciser les lignes à traiter dans une instruction UPDATE, MERGE, ou DELETE
Syntaxe¶
...
WHERE <predicate>
[ ... ]
predicate
Une expression booléenne. L’expression peut inclure des opérateurs logiques, tels que
AND
,OR
etNOT
.
Notes sur l’utilisation¶
Les prédicats de la clause WHERE se comportent comme s’ils étaient évalués après la clause FROM (bien que l’optimiseur puisse réorganiser les prédicats s’il n’y a pas d’incidence sur les résultats). Par exemple, si un prédicat de la clause WHERE fait référence aux colonnes d’une table participant à une jointure externe de la clause FROM, le filtre agit sur les lignes renvoyées par la jointure (pouvant être complétées avec des NULLs).
Faites attention lorsque vous créez des expressions qui pourraient correspondre à des valeurs NULLs.
Dans la plupart des contextes, l’expression booléenne
NULL = NULL
renvoie NULL et non TRUE. Pensez à utiliser IS [ NOT ] NULL pour comparer les valeurs NULL.Dans une clause
WHERE
, si une expression correspond à NULL, la ligne correspondant à cette expression est supprimée du jeu de résultats (c’est-à-dire qu’elle est filtrée).
Le nombre maximum d’expressions dans une liste est 16 384. Par exemple, la limite s’applique au nombre d’expressions dans l’instruction SELECT suivante :
SELECT column_x FROM mytable WHERE column_y IN (<expr1>, <expr2>, <expr3> ...);
Pour éviter d’atteindre la limite, effectuez une jointure avec une table de recherche contenant les valeurs de l’expression, plutôt que de spécifier les valeurs à l’aide de la clause IN. Par exemple, lorsque les valeurs de l’expression de l’exemple précédent sont ajoutées à une table de recherche nommée
mylookuptable
, vous pouvez exécuter la requête suivante avec succès, même si la table de recherche comporte plus de 16 384 lignes :SELECT column_x FROM mytable t JOIN mylookuptable l ON t.column_y = l.values_for_comparison;
Jointures dans la clause WHERE¶
Bien que la clause WHERE
soit principalement destinée au filtrage, la clause WHERE
peut également être utilisée pour exprimer de nombreux types de jointures. Pour des informations conceptuelles sur les jointures, voir Utilisation des jointures (ou jonctions).
Une clause WHERE
peut spécifier une jointure en incluant des conditions de jointure, qui sont des expressions booléennes définissant quelle(s) ligne(s) d’un côté de la jointure (JOIN) correspond(ent) à une(des) ligne(s) de l’autre côté de la jointure.
Les deux requêtes équivalentes suivantes montrent comment exprimer une jointure interne dans les clauses WHERE
ou 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;
Les jointures externes peuvent être spécifiées en utilisant la syntaxe (+)
dans la clause WHERE
ou les mots-clés OUTER JOIN
dans la clause FROM.
Lorsque vous spécifiez une jointure externe avec (+)
, la clause WHERE applique (+)
à chaque colonne de jointure de la table qui est « interne » (définie ci-dessous).
Note
Le résultat d’une jointure externe contient une copie de toutes les lignes d’une table. Dans cette rubrique, la table dont les lignes sont conservées est appelée la table « externe » et l’autre table est appelée la table « interne ».
Dans une instruction LEFT OUTER JOIN, la table de gauche est la table externe et la table de droite est la table interne.
Dans une instruction RIGHT OUTER JOIN, la table de droite est la table externe et la table de gauche est la table interne.
Les requêtes suivantes présentent des jointures externes gauches équivalentes, dont l’une spécifie la jointure dans la clause FROM
et l’autre dans la clause 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(+);
Dans la deuxième requête, le (+)
est à droite et identifie la table interne.
Voici un exemple de résultats pour les deux requêtes :
+-------+-------+ | T1.C1 | T2.C2 | |-------+-------| | 1 | 1 | | 2 | NULL | | 3 | 3 | | 4 | NULL | +-------+-------+
Si vous joignez une table sur plusieurs colonnes, utilisez la notation (+)
sur chaque colonne de la table interne (t2
dans l’exemple ci-dessous) :
SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+) AND t1.c3 = t2.c4 (+);Note
Il existe de nombreuses restrictions quant à l’emplacement où l’annotation
(+)
peut apparaître. Les jointures externes de la clause FROM sont plus expressives. Snowflake suggère d’utiliser la notation(+)
uniquement lors du transfert de code utilisant déjà cette notation. Le nouveau code devrait éviter cette notation.Les restrictions comprennent :
Vous ne pouvez pas utiliser la notation
(+)
pour créerFULL OUTER JOIN
. Vous ne pouvez créer queLEFT OUTER JOIN
etRIGHT OUTER JOIN
. Ceci n’est pas valide. L’instruction provoque le message d’erreur suivant :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 (+);Si une table participe à plus d’une jointure dans une requête, la notation
(+)
peut spécifier la table comme table interne dans seulement une de ces jointures. Ce qui suit n’est pas valide, cart1
sert de table interne dans deux jointures. L’instruction provoque le message d’erreur suivant :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;Notez cependant que vous pouvez utiliser
(+)
pour identifier différentes tables comme tables internes dans différentes jointures dans la même instruction SQL. L’exemple suivant joint trois tables :t1
,t2
, ett3
, dont deux sont des tables internes (dans des jointures différentes). Cette instruction fonctionne :
Une instruction LEFT OUTER JOIN entre
t1
ett2
(oùt2
est la table intérieure).Une instruction LEFT OUTER JOIN entre
t2
ett3
(oùt3
est la table intérieure).select t1.c1 from t1, t2, t3 where t1.c1 = t2.c2 (+) and t2.c2 = t3.c3 (+);
Le (+)
peut être immédiatement adjacent au nom de la table et de la colonne, ou être séparé par un espace. Les deux éléments suivants sont valides :
where t1.c1 = t2.c2(+) where t1.c1 = t2.c2 (+)
Une requête peut contenir des jointures spécifiées à la fois dans la clause FROM ... ON ...
et dans la clause WHERE
. Cependant, le fait de spécifier des jointures dans différentes clauses d’une même requête peut rendre cette dernière plus difficile à lire.
La prise en charge des jointures dans la clause WHERE
est principalement destinée à assurer la compatibilité ascendante avec les anciennes requêtes qui n’utilisent pas la syntaxe FROM ... ON ...
. Snowflake recommande d’utiliser FROM ... ON ...
lors de l’écriture de nouvelles requêtes avec des jointures. Pour plus de détails, voir JOIN.
Exemples¶
Exemples simples de filtrage¶
Les exemples suivants montrent quelques utilisations simples de la clause WHERE :
SELECT * FROM invoices WHERE invoice_date < '2018-01-01'; SELECT * FROM invoices WHERE invoice_date < '2018-01-01' AND paid = FALSE;
Cet exemple utilise une sous-requête et affiche toutes les factures dont le montant de facturation est inférieur à la moyenne :
SELECT * FROM invoices WHERE amount < ( SELECT AVG(amount) FROM invoices ) ;
Exécuter des jointures dans la clause WHERE
¶
Pour spécifier une jointure dans la clause WHERE
, énumérez les tables à joindre dans FROM clause
, en séparant les tables par une virgule. Spécifiez la condition de jointure comme un filtre dans la clause WHERE
, comme indiqué dans l’exemple suivant :
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 | +------+------+
Note
L’opérateur virgule est l’ancienne syntaxe de INNER JOIN
. L’instruction suivante montre la façon recommandée de réaliser une jointure en utilisant une syntaxe plus récente. La requête ci-dessous est équivalente à la requête ci-dessus :
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 | +------+------+
La section suivante montre les jointures de table 3 et montre la différence de comportement avec les opérateurs de jointures extérieures 0, 1 ou 2 (+)
.
Avant d’exécuter les requêtes, créez et chargez les tables à utiliser dans les jointures :
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) ;Exécutez une jointure intérieure à 3 voies. Ceci n’utilise pas
(+)
(ou le mot-clé OUTER) et est donc une jointure intérieure. La sortie ne comprend que les lignes pour lesquelles il existe un département, un projet et un employé :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 | +------------------+-------------------------------+------------------+Effectuer une jointure extérieure. Cela est similaire à l’instruction précédente sauf que celle-ci utilise
(+)
pour faire de la deuxième jointure une jointure extérieure droite. L’effet est que si un département est inclus dans la sortie, alors tous les projets de ce département sont inclus, même si ces projets n’ont pas d’employés :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 | +----------------------------------+-------------------------------+------------------+Effectuer deux jointures extérieures. Cela est similaire à l’instruction précédente sauf que celle-ci utilise
(+)
pour faire des deux jointures des jointures extérieures. L’effet est que tous les départements sont inclus (même s’ils n’ont pas encore de projets ou d’employés) et tous les projets associés aux départements sont inclus (même s’ils n’ont pas encore d’employés). Notez que la sortie exclut les projets qui n’ont pas de département.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 | +----------------------------------------------+-------------------------------+------------------+
(N’oubliez pas, cependant, que Snowflake recommande d’utiliser le mot-clé OUTER
dans la clause FROM
plutôt que d’utiliser l’opérateur (+)
dans la clause WHERE
).