9.24. Expressões de subconsulta #

9.24.1. EXISTS
9.24.2. IN
9.24.3. NOT IN
9.24.4. ANY / SOME
9.24.5. ALL
9.24.6. Comparação de uma única linha
9.24.7. Exemplo do tradutor

Esta seção descreve as expressões de subconsulta em conformidade com o padrão SQL disponíveis no PostgreSQL. Todas as formas de expressão documentadas nesta seção retornam resultados booleanos (verdade/falso).

9.24.1. EXISTS #

EXISTS (subconsulta)

O argumento de EXISTS é uma declaração SELECT arbitrária, ou uma subconsulta. A subconsulta é avaliada para determinar se retorna alguma linha. Se retornar ao menos uma linha, o resultado de EXISTS será verdade; se a subconsulta não retornar nenhuma linha, o resultado de EXISTS será falso.

A subconsulta pode fazer referência a variáveis da consulta que a engloba, que atuarão como constantes durante qualquer avaliação da subconsulta.

Geralmente a subconsulta só é executada pelo tempo suficiente para determinar se ao menos uma linha será retornada, e não até o fim. Não é recomendável escrever uma subconsulta que produza efeitos colaterais (como chamar funções de sequência); a ocorrência dos efeitos colaterais não pode ser prevista.

Uma vez que o resultado depende apenas de alguma linha ser retornada, e não do conteúdo dessas linhas, normalmente a lista de saída da subconsulta não é importante. Uma convenção de codificação comum é escrever todas as condições EXISTS na forma EXISTS(SELECT 1 WHERE ...). No entanto, existem exceções a essa regra, como as subconsultas que usam INTERSECT.

Este exemplo simples funciona como uma junção interna usando a coluna col2, mas produz no máximo uma linha de saída para cada linha da tabela tab1, mesmo havendo várias linhas correspondentes na tabela tab2:

SELECT col1
FROM tab1
WHERE EXISTS (SELECT 1 FROM tab2 WHERE col2 = tab1.col2);

9.24.2. IN #

expressão IN (subconsulta)

O lado direito é uma subconsulta entre parênteses, que deve retornar exatamente uma coluna. A expressão à esquerda é avaliada e comparada com cada linha do resultado da subconsulta. O resultado de IN será verdade se for encontrada alguma linha igual na subconsulta. O resultado será falso se não for encontrada nenhuma linha igual (incluindo o caso onde a subconsulta não retorna nenhuma linha).

Note que se a expressão à esquerda resultar em nulo, ou se não houver valores iguais à direita e pelo menos uma linha à direita resultar em nulo, o resultado da construção IN será nulo, e não falso. Isso está em acordo com as regras normais do padrão SQL para combinações booleanas de valores nulos.

Assim como em EXISTS, não é recomendável assumir que a subconsulta será executada até o fim.

construtor_de_linha IN (subconsulta)

O lado esquerdo desta forma de IN é um construtor de linha, conforme descrito na Seção 4.2.13. O lado direito é uma subconsulta entre parênteses, que deve retornar exatamente tantas colunas quantas forem as expressões na linha à esquerda. As expressões do lado esquerdo são avaliadas e comparadas linha a linha com cada linha do resultado da subconsulta. O resultado de IN será verdade se for encontrada alguma linha igual na subconsulta. O resultado será falso se não for encontrada nenhuma linha igual na subconsulta (incluindo o caso onde a subconsulta não retorna nenhuma linha).

Como de costume, os valores nulos nas linhas são combinados segundo as regras normais das expressões booleanas do padrão SQL. Duas linhas são consideradas iguais se todos os seus membros correspondentes forem não nulos e iguais; as linhas não são iguais se algum membro correspondente for não nulo e diferente; senão, o resultado dessa comparação de linha é desconhecido (nulo). Se todos os resultados por linha forem não iguais ou nulos, com pelo menos um nulo, o resultado de IN será nulo.

9.24.3. NOT IN #

expressão NOT IN (subconsulta)

O lado direito é uma subconsulta entre parênteses, que deve retornar exatamente uma coluna. A expressão à esquerda é avaliada e comparada com cada linha do resultado da subconsulta. O resultado de NOT IN será verdade se forem encontradas somente linhas não iguais na subconsulta (incluindo o caso onde a subconsulta não retorna nenhuma linha). O resultado será falso se for encontrada alguma linha igual.

Note que, se a expressão à esquerda resultar em nulo, ou se não houver valores iguais à direita e pelo menos uma linha à direita resultar em nulo, o resultado da construção NOT IN será nulo, e não verdade. Isto está em acordo com as regras normais do padrão SQL para combinações booleanas de valores nulos.

Assim como em EXISTS, não é recomendável assumir que a subconsulta será executada até o fim.

construtor_de_linha NOT IN (subconsulta)

O lado esquerdo desta forma de NOT IN é um construtor de linha, conforme descrito na Seção 4.2.13. O lado direito é uma subconsulta entre parênteses, que deve retornar exatamente tantas colunas quantas forem as expressões na linha à esquerda. As expressões do lado esquerdo são avaliadas e comparadas linha a linha com cada linha do resultado da subconsulta. O resultado de NOT IN será verdade se forem encontradas apenas linhas não iguais na subconsulta (incluindo o caso onde a subconsulta não retorna nenhuma linha). O resultado será falso se for encontrada alguma linha igual na subconsulta.

Como de costume, os valores nulos nas linhas são combinados segundo as regras normais das expressões booleanas do padrão SQL. Duas linhas são consideradas iguais se todos os seus membros correspondentes forem não nulos e iguais; as linhas não são iguais se algum membro correspondente for não nulo e diferente; senão, o resultado dessa comparação de linha é desconhecido (nulo). Se todos os resultados por linha forem não iguais ou nulos, com pelo menos um nulo, o resultado de NOT IN será nulo.

9.24.4. ANY / SOME #

expressão operador ANY (subconsulta)
expressão operador SOME (subconsulta)

O lado direito é uma subconsulta entre parênteses, que deve retornar exatamente uma coluna. A expressão à esquerda é avaliada e comparada com cada linha do resultado da subconsulta usando o operador fornecido, que deve produzir um resultado booleano. O resultado de ANY será verdade se for obtido algum resultado verdade. O resultado será falso se não for obtido nenhum resultado verdade (incluindo o caso onde a subconsulta não retorna nenhuma linha).

SOME é sinônimo de ANY; IN equivale a = ANY.

Note que caso não haja sucessos, e pelo menos uma linha à direita produzir nulo para o resultado do operador, o resultado da construção ANY será nulo, e não falso. Isso está em acordo com as regras normais do padrão SQL para combinações booleanas de valores nulos.

Assim como em EXISTS, não é recomendável assumir que a subconsulta será executada até o fim.

construtor_de_linha operador ANY (subconsulta)
construtor_de_linha operador SOME (subconsulta)

O lado esquerdo desta forma de ANY é um construtor de linha, conforme descrito na Seção 4.2.13. O lado direito é uma subconsulta entre parênteses, que deve retornar exatamente tantas colunas quantas forem as expressões na linha à esquerda. As expressões do lado esquerdo são avaliadas e comparadas linha a linha com cada linha do resultado da subconsulta, usando o operador fornecido. O resultado de ANY será verdade se a comparação retornar verdade para qualquer linha da subconsulta. O resultado será falso se a comparação retornar falso para todas as linhas da subconsulta (incluindo o caso onde a subconsulta não retorna nenhuma linha). O resultado será nulo se nenhuma comparação com uma linha da subconsulta retornar verdade e pelo menos uma comparação retornar nulo.

Veja a Seção 9.25.5 para obter detalhes sobre o significado de uma comparação de construtor de linha.

9.24.5. ALL #

expressão operador ALL (subconsulta)

O lado direito é uma subconsulta entre parênteses, que deve retornar exatamente uma coluna. A expressão à esquerda é avaliada e comparada com cada linha do resultado da subconsulta usando o operador fornecido, que deve produzir um resultado booleano. O resultado de ALL será verdade se todas as linhas produzirem verdade (incluindo o caso onde a subconsulta não retorna nenhuma linha). O resultado será falso se for encontrado algum resultado falso. O resultado será nulo se nenhuma comparação com uma linha da subconsulta retornar falso e pelo menos uma comparação retornar nulo.

NOT IN equivale a <> ALL.

Assim como em EXISTS, não é recomendável assumir que a subconsulta será executada até o fim.

construtor_de_linha operador ALL (subconsulta)

O lado esquerdo desta forma de ALL é um construtor de linha, conforme descrito na Seção 4.2.13. O lado direito é uma subconsulta entre parênteses, que deve retornar exatamente tantas colunas quantas forem as expressões na linha da esquerda. As expressões do lado esquerdo são avaliadas e comparadas linha a linha com cada linha do resultado da subconsulta, usando o operador fornecido. O resultado de ALL será verdade se a comparação retornar verdade para todas as linhas da subconsulta (incluindo o caso onde a subconsulta não retorna nenhuma linha). O resultado será falso se a comparação retornar falso para qualquer linha da subconsulta. O resultado será nulo se nenhuma comparação com uma linha da subconsulta retornar falso e pelo menos uma comparação retornar nulo.

Veja a Seção 9.25.5 para obter detalhes sobre o significado de uma comparação de construtor de linha.

9.24.6. Comparação de uma única linha #

construtor_de_linha operador (subconsulta)

O lado esquerdo é um construtor de linha, conforme descrito na Seção 4.2.13. O lado direito é uma subconsulta entre parênteses, que deve retornar exatamente tantas colunas quantas forem as expressões na linha à esquerda. Além disso, a subconsulta não pode retornar mais de uma linha. (Se retornar zero linhas, o resultado será considerado nulo.) O lado esquerdo é avaliado e comparado com a linha do resultado de uma única linha da subconsulta.

Veja a Seção 9.25.5 para obter detalhes sobre o significado de uma comparação de construtor de linha.

9.24.7. Exemplo do tradutor #

Exemplo 9.10. Expressões EXISTS, ANY e ALL

Este exemplo usa EXISTS, ANY, autojunção e GROUP BY para mostrar os nomes dos departamentos com algum salário maior ou igual a 5000, e usa ALL para mostrar o nome do departamento com todos os salários menores que 5000.

As consultas deste exemplo usam a mesma tabela salario_emp vista na Seção 3.5, e na Seção 9.22.

-- Condição EXISTS

SELECT DISTINCT nome_dep
FROM salario_emp AS se1
WHERE EXISTS (
    SELECT 1
    FROM salario_emp AS se2
    WHERE se1.nome_dep = se2.nome_dep
    AND se2.salario >= 5000
);
    nome_dep
-----------------
 vendas
 desenvolvimento
(2 linhas)
-- Condição ANY

SELECT DISTINCT nome_dep
FROM salario_emp se1
WHERE 5000 <= ANY (SELECT salario
    FROM salario_emp AS se2
    WHERE se1.nome_dep = se2.nome_dep);
    nome_dep
-----------------
 desenvolvimento
 vendas
(2 linhas)
-- Autojunção

SELECT DISTINCT nome_dep
FROM salario_emp AS se1
     INNER JOIN salario_emp AS se2 USING(nome_dep)
WHERE se2.salario >= 5000;
    nome_dep
-----------------
 vendas
 desenvolvimento
(2 linhas)
-- GROUP BY

SELECT nome_dep
FROM salario_emp
GROUP BY nome_dep
HAVING max(salario) >= 5000;
    nome_dep
-----------------
 vendas
 desenvolvimento
(2 linhas)
 -- ALL

SELECT DISTINCT nome_dep
FROM salario_emp se1
WHERE 5000 > ALL (SELECT salario
    FROM salario_emp AS se2
    WHERE se1.nome_dep = se2.nome_dep);
 nome_dep
----------
 pessoal
(1 linha)