Categorias:

Sintaxe de consulta

WHERE

A cláusula WHERE especifica uma condição que atua como um filtro. Você pode usar a cláusula WHERE para:

Sintaxe

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

Uma expressão booleana. A expressão pode incluir operadores lógicos, tais como AND, OR e NOT.

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).

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;
Copy

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(+);
Copy

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 |
+-------+-------+
Copy

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 (+);
Copy

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 criar FULL OUTER JOIN; você só pode criar LEFT OUTER JOIN e RIGHT 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 (+);
    
    Copy
  • 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 porque t1 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;
    
    Copy

    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 e t3, duas das quais sendo tabelas internas (em diferentes junções). Esta instrução executa:

    • Uma LEFT OUTER JOIN entre t1 e t2 (em que t2 é a tabela interior).

    • Uma LEFT OUTER JOIN entre t2 e t3 (em que t3 é a tabela interior).

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

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 (+)
Copy

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;
Copy

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
                   )
    ;
Copy

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 |
+------+------+
Copy

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 |
+------+------+
Copy

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)
    ;
Copy

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       |
+------------------+-------------------------------+------------------+
Copy

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             |
+----------------------------------+-------------------------------+------------------+
Copy

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             |
+----------------------------------------------+-------------------------------+------------------+
Copy

(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).