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).
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);
expressãoIN (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_linhaIN (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.
expressãoNOT 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_linhaNOT 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.
expressãooperadorANY (subconsulta)expressãooperadorSOME (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_linhaoperadorANY (subconsulta)construtor_de_linhaoperadorSOME (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.
expressãooperadorALL (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_linhaoperadorALL (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.
construtor_de_linhaoperador(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.
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)