Definimos o que significa subconsulta e mostramos as diferentes subconsultas que se podem fazer.Por Claudio
Publicado em: 12/11/07
Uma subconsulta é uma instrução SELECT adicionada dentro de uma instrução SELECT, SELECT...INTO, INSERT...INTO, DELETE, ou UPDATE ou dentro de outra subconsulta. Pode utilizar três formas de sintaxe para criar uma subconsulta:
comparação [ANY | ALL | SOME] (instrução sql)
expressão [NOT] IN (instrução sql)
[NOT] EXISTS (instrução sql)
Onde:
| comparação | É uma expressão e um operador de comparação que compara a expressão com o resultado da subconsulta. |
| expressão | É uma expressão pela qual se busca o conjunto resultante da subconsulta. |
| instrução SQL | É uma instrução SELECT, que segue o mesmo formato e regras que qualquer outra SELECT. Deve ir entre parênteses. |
Pode-se utilizar uma subconsulta no lugar de uma expressão na lista de campos de uma instrução SELECT ou em uma cláusula WHERE ou HAVING. Em uma subconsulta, se utiliza uma instrução SELECT para proporcionar um conjunto de um ou mais valores especificados para avaliar na expressão da cláusula WHERE ou HAVING.
Pode-se utilizar o predicado ANY ou SOME, os quais são sinônimos, para recuperar registros da consulta principal, que satisfaçam a comparação com qualquer outro registro recuperado na subconsulta. O exemplo seguinte devolve todos os produtos cujo preço unitário for maior que o de qualquer produto vendido com um desconto igual ou maior ao 25 por cento:
SELECT *
FROM
Produtos
WHERE
PrecoUnidade
ANY
(
SELECT
PrecoUnidade
FROM
DetalhePedido
WHERE
Desconto = 0 .25
)
O predicado ALL se utiliza para recuperar unicamente aqueles registros da consulta principal que satisfazem a comparação com todos os registros recuperados na subconsulta. Se se muda ANY por ALL no exemplo anterior, a consulta devolverá unicamente aqueles produtos cujo preço unitário for maior que o de todos os produtos vendidos com um desconto igual ou maior ao 25 por cento. Isto é muito mais restritivo.
O predicado IN se emprega para recuperar unicamente aqueles registros da consulta principal para os que alguns registros da subconsulta contém um valor igual. O exemplo seguinte devolve todos os produtos vendidos com um desconto igual ou maior ao 25 por cento:
SELECT *
FROM
Produtos
WHERE
IDProduto
IN
(
SELECT
IDProduto
FROM
DetalhePedido
WHERE
Desconto = 0.25
)
Inversamente, pode-se utilizar NOT IN para recuperar unicamente aqueles registros da consulta principal para os que não têm nenhum registro da subconsulta que contenha um valor igual.
O predicado EXISTS (com palavra reservada NOT opcional) se utiliza em comparações de verdade/falso para determinar se a subconsulta devolve algum registro. Suponhamos que desejamos recuperar todos aqueles clientes que tiverem realizado pelo menos um pedido:
SELECT
Clientes.Companhia, Clientes.Telefone
FROM
Clientes
WHERE EXISTS (
SELECT
FROM
Pedidos
WHERE
Pedidos.IdPedido = Clientes.IdCliente
)
Esta consulta é equivalente a esta outra:
SELECT
Clientes.Companhia, Clientes.Telefone
FROM
Clientes
WHERE
IdClientes
IN
(
SELECT
Pedidos.IdCliente
FROM
Pedidos
)
Pode-se utilizar também alias do nome da tabela em uma subconsulta para se referir às tabelas listadas na cláusula FROM fora da subconsulta. O exemplo seguinte devolve os nomes dos empregados cujo salário for igual ou maior do que o salário médio de todos os empregados com o mesmo título. À tabela Empregados foi dado o alias T1:
SELECT
Sobrenome, Nome, Titulo, Salario
FROM
Empregados AS T1
WHERE
Salario =
(
SELECT
Avg(Salario)
FROM
Empregados
WHERE
T1.Titulo = Empregados.Titulo
)
ORDER BY Titulo
No exemplo anterior, a palavra reservada AS é opcional.
SELECT
Sobrenomes, Nome, Cargo, Salario
FROM
Empregados
WHERE
Cargo LIKE 'Agente Ven*'
AND
Salario ALL
(
SELECT
Salario
FROM
Empregados
WHERE
Cargo LIKE '*Chefe*'
OR
Cargo LIKE '*Diretor*'
)
(Obtém uma lista com o nome, cargo e salário de todos os agentes de ventas cujo salário for maior que o de todos os chefes e diretores.)
SELECT DISTINCT
NomeProduto, Preco_Unidade
FROM
Produtos
WHERE
PrecoUnidade =
(
SELECT
PrecoUnidade
FROM
Produtos
WHERE
NomeProduto = 'Almíbar anisado'
)
(Obtém uma lista com o nome e o preço unitário de todos os produtos com o mesmo preço que o almíbar anisado.)
SELECT DISTINCT
NomeContato, NomeCompanhia, CargoContato, Telefone
FROM
Clientes
WHERE
IdCliente IN (
SELECT DISTINCT IdCliente
FROM Pedidos
WHERE DataPedido <#07/01/1993#
)
(Obtém uma lista das companhias e dos contatos de todos os clientes que realizaram um pedido no segundo trimestre de 1993.)
SELECT
Nome, Sobrenomes
FROM
Empregados AS E
WHERE EXISTS
(
SELECT *
FROM
Pedidos AS O
WHERE O.IdEmpregado = E.IdEmpregado
)
(Seleciona o nome de todos os empregados que reservaram pelo menos um pedido.)
SELECT DISTINCT
Pedidos.Id_Produto, Pedidos.Quantidade,
(
SELECT
Produtos.Nome
FROM
Produtos
WHERE
Produtos.IdProduto = Pedidos.IdProduto
) AS ElProduto
FROM
Pedidos
WHERE
Pedidos.Quantidade = 150
ORDER BY
Pedidos.Id_Produto
(Recupera o Código do Produto e a Quantidade pedida da tabela pedidos, extraindo o nome do produto da tabela de produtos.)
SELECT
NumVoo, Lugares
FROM
Voos
WHERE
Origem = 'Madri'
AND Exists (
SELECT T1.NumVoo FROM Voos AS T1
WHERE T1.LuagaresLivres > 0 AND T1.NumVuelo=Vuelos.NumVuelo)
(Recupera números de vôo e capacidades de aqueles vôos com destino Madri e lugares livres
Suponhamos agora que temos uma tabela com os identificadores de todos nossos produtos e o stock de cada um deles. Em outra tabela se encontram todos os pedidos que temos pendentes de servir. Trata-se de averiguar que produtos não se podem servir por falta de estoque.
SELECT
PedidosPendentes.Nome
FROM
PedidosPendentes
GROUP BY
PedidosPendentes.Nome
HAVING
SUM(PedidosPendentes.Quantidade <
(
SELECT
Produtos.Estoque
FROM
Produtos
WHERE
Produtos.IdProduto = PedidosPendentes.IdProduto
)
)
Suponhamos que em nossa tabela de empregados desejamos buscar todas as mulheres cuja idade seja maior da de qualquer homem:
SELECT
Empregados.Nome
FROM
Empregados
WHERE
Sexo = 'M' AND Idade > ANY
(SELECT Empregados.Idade FROM Empregados WHERE Sexo ='H')
Ou o que seria o mesmo:
SELECT
Empregados.Nome
FROM
Empregados
WHERE
Sexo = 'M' AND Idade >
(SELECT Max( Empregados.Idade )FROM Empregados WHERE Sexo ='H')
A seguinte tabela mostra algum exemplo do operador ANY e ALL
| Valor 1 | Operador | Valor 2 | Resultado |
| 3 | > ANY | (2,5,7) | Certo |
| 3 | = ANY | (2,5,7) | Falso |
| 3 | = ANY | (2,3,5,7) | Certo |
| 3 | > ALL | (2,5,7) | Falso |
| 3 | < ALL | (5,6,7) | Falso |
A operação =ANY é equivalente ao operador IN, ambos devolvem o mesmo resultado.
Comentários do artigo
Foi enviado 1 comentário ao artigo

1 comentário revisado:
No caso do "3 < ALL (5,6,7) Falso"
o resultado é Verdadeiro, pois equivale ao seguinte:
(3<5) AND (3<6) AND 3<7), trocando em miúdos TRUE AND TRUE AND TRUE resulta em TRUE.