Seu navegador não oferece leitura em voz alta. Você pode ler o guia normalmente.
Uma consulta dentro de outra (subconsulta) e as operações que combinam resultados (UNION e companhia) completam o repertório de SQL cobrado em provas de TI. Todos os resultados abaixo vêm da execução das consultas em um banco de teste, com os mesmos dados fictícios dos outros guias da série. Se precisar do básico, comece em SELECT, WHERE, ORDER BY, LIKE e IN.
Os dados
servidor (id, nome, unidade_id, cargo, horas_extras, tempo_servico):
| id | nome | unidade_id | cargo | horas_extras | tempo_servico |
|---|---|---|---|---|---|
| 1 | Ana Lima | 1 | Analista | 10 | 5 |
| 2 | Bruno Souza | 1 | Tecnico | 4 | 12 |
| 3 | Carla Dias | 2 | Analista | NULL | 3 |
| 4 | Diego Alves | 2 | Analista | 8 | 9 |
| 5 | Elisa Rocha | 3 | Tecnico | 0 | 7 |
| 6 | Fabio Nunes | NULL | Analista | 6 | 2 |
| 7 | Gabi Matos | 2 | Tecnico | NULL | 15 |
unidade: 1 Protocolo, 2 Compras, 3 Arquivo, 4 Ouvidoria.
Subconsulta escalar
Uma subconsulta que devolve um único valor pode ser usada onde um valor caberia, como em uma comparação:
SELECT nome, tempo_servico FROM servidor
WHERE tempo_servico > (SELECT AVG(tempo_servico) FROM servidor)
ORDER BY id;
A média de tempo de serviço é 7,571… (53 dividido por 7). Quem passa dela: Bruno Souza (12), Diego Alves (9) e Gabi Matos (15). A subconsulta é calculada uma vez. Se ela devolver mais de uma linha onde só se admite um valor, a consulta gera erro.
Subconsulta com IN
IN compara com o conjunto de valores devolvido por uma subconsulta de uma coluna:
SELECT nome FROM unidade
WHERE id IN (SELECT unidade_id FROM servidor WHERE cargo = 'Tecnico')
ORDER BY id;
Resultado: Protocolo, Compras e Arquivo, as unidades que têm ao menos um técnico (Bruno, Gabi e Elisa). A Ouvidoria não aparece, porque não tem servidor algum.
Subconsulta correlacionada e EXISTS
Na subconsulta correlacionada, a consulta interna usa colunas da externa e, conceitualmente, é reavaliada para cada linha da externa. O EXISTS testa se a subconsulta devolve pelo menos uma linha; o conteúdo selecionado é irrelevante (por convenção, escreve-se SELECT 1).
SELECT nome FROM unidade u
WHERE EXISTS (SELECT 1 FROM servidor s WHERE s.unidade_id = u.id)
ORDER BY id;
Resultado: Protocolo, Compras e Arquivo, as unidades com servidor. O inverso, NOT EXISTS, devolveria só a Ouvidoria.
IN ou EXISTS?
| Aspecto | IN | EXISTS |
|---|---|---|
| Como funciona | compara com o conjunto devolvido | testa existência de linhas |
| Valores NULL | pode causar surpresas com NOT IN |
trata bem o NULL |
| Desempenho | depende do otimizador; sistemas modernos costumam tratar os dois de forma parecida | idem |
A diferença decisiva aparece na negação. Quem não está em Compras?
-- com NOT IN
SELECT nome FROM servidor
WHERE unidade_id NOT IN (SELECT id FROM unidade WHERE nome = 'Compras');
Resultado: Ana, Bruno e Elisa. Fabio, sem unidade (NULL), foi omitido, porque NULL NOT IN (2) resulta em desconhecido.
-- com NOT EXISTS
SELECT nome FROM servidor
WHERE NOT EXISTS (SELECT 1 FROM unidade u
WHERE u.id = servidor.unidade_id AND u.nome = 'Compras')
ORDER BY id;
Resultado: Ana, Bruno, Elisa e Fabio. Aqui Fabio entra. As duas consultas parecem equivalentes e não são; a razão está no tratamento de NULL, explicada em NULL no SQL e a lógica de três valores.
Operações de conjunto
Combinam os resultados de duas consultas com o mesmo número de colunas e tipos compatíveis, empilhando linhas (ao contrário do JOIN, que une colunas).
Consultas-base:
- Consulta X:
SELECT id FROM servidor WHERE tempo_servico > 8, que devolve os ids 2, 4 e 7. - Consulta Y:
SELECT id FROM servidor WHERE horas_extras > 5, que devolve os ids 1, 4 e 6.
| Operação | O que faz | Resultado com X e Y |
|---|---|---|
X UNION Y |
junta e elimina repetidos | 1, 2, 4, 6, 7 |
X UNION ALL Y |
junta e mantém repetidos | 2, 4, 7, 1, 4, 6 (seis linhas; o 4 aparece duas vezes) |
X INTERSECT Y |
só o que está nos dois | 4 |
X EXCEPT Y |
o que está em X e não em Y | 2 e 7 |
Observações: o UNION compara linhas inteiras para eliminar duplicidades, o que custa uma etapa a mais de processamento; por isso o UNION ALL costuma ser mais rápido quando se sabe que não há repetidos ou que eles não importam. O EXCEPT não é simétrico: Y EXCEPT X daria 1 e 6. Em alguns sistemas, o EXCEPT chama-se MINUS, e INTERSECT e EXCEPT podem não existir; confira o sistema da questão. A ordem de linhas do resultado de uma operação de conjunto só é garantida com ORDER BY no final.
Outro exemplo, com texto: SELECT cargo FROM servidor WHERE tempo_servico > 8 UNION SELECT cargo FROM servidor WHERE horas_extras > 5 devolveu apenas Analista e Tecnico (duas linhas), enquanto o UNION ALL equivalente devolveu seis linhas, com repetições.
Quando usar cada ferramenta
| Necessidade | Ferramenta |
|---|---|
| comparar com um valor calculado (média, máximo) | subconsulta escalar |
| manter linhas cujo valor pertence a um conjunto | IN |
| verificar existência de linha relacionada | EXISTS |
| listar quem não tem relação | NOT EXISTS ou LEFT JOIN ... IS NULL |
| juntar colunas de tabelas relacionadas | JOIN |
| empilhar resultados de consultas parecidas | UNION |
Muitas subconsultas podem ser reescritas como JOIN e vice-versa. Em provas, o que se cobra é entender o resultado de cada forma e o efeito do NULL.
Passo a passo para ler uma consulta aninhada
- Resolva primeiro a subconsulta mais interna, anotando o que ela devolve.
- Substitua mentalmente a subconsulta por esse resultado.
- Aplique a consulta externa.
- Se for correlacionada, repita o raciocínio linha a linha da externa.
- Em operações de conjunto, resolva cada lado antes de combinar.
Erros comuns
- Usar subconsulta escalar que devolve várias linhas.
- Usar
NOT INquando a coluna pode ter NULL. - Esquecer que
UNIONelimina duplicados eUNION ALLnão. - Combinar consultas com números de colunas diferentes.
- Achar que
EXCEPTé simétrico.
Fontes e atualização
Não há norma oficial brasileira sobre a linguagem SQL; o conteúdo segue o padrão da linguagem, e todos os resultados foram obtidos executando as consultas em um banco de teste. Operadores como INTERSECT, EXCEPT e MINUS variam entre sistemas: confira o edital.
Próximos passos
- Aprofunde junções em SQL JOIN: INNER, LEFT, RIGHT, FULL e CROSS.
- Pratique agregações em GROUP BY, HAVING e funções de agregação.
- Revise a visão geral em bancos de dados: chaves, normalização, SQL e transações.