- Categorias:
WHERE¶
A cláusula WHERE
especifica uma condição que atua como um filtro. Você pode usar a cláusula WHERE
para:
Filtrar o resultado da cláusula FROM em uma instrução SELECT.
Especificar em quais linhas operar em um UPDATE, MERGE ou DELETE.
Sintaxe¶
...
WHERE <predicate>
[ ... ]
predicate
Uma expressão booleana. A expressão pode incluir operadores lógicos, tais como
AND
,OR
eNOT
.
Notas de uso¶
Os predicados na cláusula WHERE comportam-se como se fossem avaliados conforme a cláusula FROM (embora o otimizador possa reordenar os predicados se isso não impactar os resultados). Por exemplo, se um predicado na cláusula WHERE fizer referência às colunas de uma tabela que participa de uma junção externa na cláusula FROM, o filtro operará nas linhas retornadas da junção (que podem ser preenchidas com NULLs).
Tenha cuidado ao criar expressões que possam avaliar NULLs.
Na maioria dos contextos, a expressão booleana
NULL = NULL
retorna NULL, não TRUE. Considere usar IS [ NOT ] NULL para comparar os valores NULL.Em uma cláusula
WHERE
, se uma expressão avaliar como NULL, a linha para essa expressão será removida do conjunto de resultados (ou seja, é filtrada).
O número máximo de expressões em uma lista é 16.384. Por exemplo, o limite se aplica ao número de expressões na seguinte instrução SELECT:
SELECT column_x FROM mytable WHERE column_y IN (<expr1>, <expr2>, <expr3> ...);
Para evitar atingir o limite, execute uma junção com uma tabela de consulta que contenha os valores da expressão, em vez de especificar os valores usando a cláusula IN. Por exemplo, quando os valores da expressão no exemplo anterior são adicionados a uma tabela de consulta chamada
mylookuptable
, você pode executar a consulta a seguir com êxito, mesmo que a tabela de consulta tenha mais de 16.384 linhas:SELECT column_x FROM mytable t JOIN mylookuptable l ON t.column_y = l.values_for_comparison;
Junções na cláusula WHERE.¶
Embora a cláusula WHERE
seja principalmente para filtragem, a cláusula WHERE
também pode ser usada para expressar muitos tipos de junções. Para informações conceituais sobre as junções, consulte Como trabalhar com junções.
Uma cláusula WHERE
pode especificar uma junção ao incluir condições de junção, que são expressões booleanas que definem que linha(s) de um lado de JOIN correspondam a outra(s) linha(s) do outro lado da junção.
As duas consultas equivalentes seguintes mostram como expressar uma junção interna na cláusula 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;
As junções externas podem ser especificadas usando ou a sintaxe (+)
na cláusula WHERE
ou as palavras-chave OUTER JOIN
na cláusula FROM.
Quando você especifica uma junção externa com (+)
, a cláusula WHERE aplica (+)
a cada coluna de junção da tabela que é “interna” (definida abaixo).
Nota
O resultado de uma junção externa contém uma cópia de todas as linhas de uma tabela. Neste tópico, a tabela cujas linhas são preservadas é chamada de tabela “externa”, e a outra tabela é chamada de tabela “interna”.
Em um LEFT OUTER JOIN, a tabela da esquerda é a tabela externa e a tabela da direita é a tabela interna.
Em um RIGHT OUTER JOIN, a tabela da direita é a tabela externa e a tabela da esquerda é a tabela interna.
As consultas a seguir mostram junções externas esquerdas equivalentes, uma das quais especifica a junção na cláusula FROM
e outra especifica a junção na cláusula 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(+);
Na segunda consulta, o (+)
está do lado direito e identifica a tabela interna.
A saída de amostras para ambas as consultas está abaixo:
+-------+-------+ | T1.C1 | T2.C2 | |-------+-------| | 1 | 1 | | 2 | NULL | | 3 | 3 | | 4 | NULL | +-------+-------+
Se você estiver unindo uma tabela em várias colunas, use a notação (+)
em cada coluna na tabela interna (t2
no exemplo abaixo):
SELECT t1.c1, t2.c2 FROM t1, t2 WHERE t1.c1 = t2.c2 (+) AND t1.c3 = t2.c4 (+);Nota
Há muitas restrições sobre onde a notação
(+)
pode aparecer; as junções externas da cláusula FROM são mais expressivas. O Snowflake sugere o uso da notação(+)
somente ao portar o código que já usa essa notação. O novo código deve evitar essa notação.As restrições incluem:
Você não pode usar a notação
(+)
para criarFULL OUTER JOIN
; você só pode criarLEFT OUTER JOIN
eRIGHT OUTER JOIN
. O seguinte não é válido. A instrução causa a seguinte mensagem de erro: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 (+);Se uma tabela participa de mais de uma junção em uma consulta, a notação
(+)
pode especificar a tabela como sendo a tabela interna em apenas uma dessas junções. O seguinte não é válido porquet1
serve como a tabela interna em duas junções. A instrução causa a seguinte mensagem de erro: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;Observe, entretanto, que você pode usar
(+)
para identificar tabelas diferentes como tabelas internas em diferentes junções na mesma instrução SQL. O exemplo a seguir une três tabelas:t1
,t2
et3
, duas das quais sendo tabelas internas (em diferentes junções). Esta instrução executa:
Uma LEFT OUTER JOIN entre
t1
et2
(em quet2
é a tabela interior).Uma LEFT OUTER JOIN entre
t2
et3
(em quet3
é a tabela interior).select t1.c1 from t1, t2, t3 where t1.c1 = t2.c2 (+) and t2.c2 = t3.c3 (+);
O (+)
pode ficar imediatamente adjacente ao nome da tabela e da coluna, ou pode ser separado por um espaço em branco. Ambos os itens a seguir são válidos:
where t1.c1 = t2.c2(+) where t1.c1 = t2.c2 (+)
Uma consulta pode conter as junções especificadas tanto na cláusula FROM ... ON ...
quanto na cláusula WHERE
. No entanto, a especificação de junções em diferentes cláusulas de uma mesma consulta pode tornar essa consulta mais difícil de ler.
O suporte à junções na cláusula WHERE
é principalmente para compatibilidade retroativa com consultas antigas que não utilizam a sintaxe FROM ... ON ...
. O Snowflake recomenda usar FROM ... ON ...
ao escrever novas consultas com as junções. Para obter mais detalhes, consulte JOIN.
Exemplos¶
Exemplos simples de filtragem¶
A seguir, alguns usos simples da cláusula WHERE:
SELECT * FROM invoices WHERE invoice_date < '2018-01-01'; SELECT * FROM invoices WHERE invoice_date < '2018-01-01' AND paid = FALSE;
Este exemplo usa uma subconsulta e mostra todas as faturas que têm valores de faturamento inferiores à média:
SELECT * FROM invoices WHERE amount < ( SELECT AVG(amount) FROM invoices ) ;
Execução de junções na cláusula WHERE
¶
Para especificar uma união na cláusula WHERE
, liste as tabelas a serem unidas no FROM clause
, separando as tabelas com uma vírgula. Especifique a condição de junção como um filtro na cláusula WHERE
, como mostrado no exemplo a seguir:
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 | +------+------+
Nota
O operador de vírgula é uma sintaxe mais antiga para INNER JOIN
. A seguinte instrução mostra a forma recomendada para realizar uma junção usando uma sintaxe mais nova. A consulta abaixo é equivalente à consulta acima:
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 | +------+------+
Esta próxima seção mostra junções de 3 tabelas e exibe a diferença de comportamento com 0, 1 ou 2 operações de junção externa (+)
.
Antes de executar as consultas, criar e carregar as tabelas a serem utilizadas nas junções:
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) ;Execute uma junção interna de 3 vias. Isto não utiliza
(+)
(ou a palavra-chave OUTER) e é, portanto, uma junção interna. A saída inclui apenas linhas para as quais existe um departamento, projeto e funcionário: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 | +------------------+-------------------------------+------------------+Faça uma junção externa. Isto é semelhante à instrução anterior, exceto que isto usa
(+)
para fazer com que a segunda junção seja uma junção externa direita. O efeito é que se um departamento for incluído na saída, então todos os projetos desse departamento serão incluídos, mesmo que esses projetos não tenham funcionários: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 | +----------------------------------+-------------------------------+------------------+Faça duas junções externas. Isto é o mesmo que a instrução anterior, exceto que isto usa
(+)
para fazer com que as duas junções sejam junções externas. O efeito é que todos os departamentos são incluídos (mesmo que ainda não tenham projetos ou funcionários) e todos os projetos associados a departamentos são incluídos (mesmo que ainda não tenham funcionários). Observe que o resultado exclui projetos que não têm departamento.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 | +----------------------------------------------+-------------------------------+------------------+
(Lembre-se, entretanto, que o Snowflake recomenda usar a palavra-chave OUTER
na cláusula FROM
em vez de usar o operador (+)
na cláusula WHERE
).