MySQL: Uma explicação detalhada sobre subconsultas do MySQL…
Última atualização: 2026-08-26
As subconsultas são um recurso do SQL que permite o aninhamento — os resultados de uma consulta são usados como condição para outra consulta.
Esta aula apresenta uma explicação sistemática das diversas formas de subconsultas e sua otimização.
graph TB
A[Subquery Categories] --> B[Tag-Based Query<br/>Return a single value]
A --> C[Liezi Query<br/>Return a column]
A --> D[Row-based queries<br/>Return a line]
A --> E[Table Child Query<br/>Back to Table]
C --> C1[IN / NOT IN]
C --> C2[ANY / ALL]
E --> E1[FROM Derivation Table]
A --> F[EXISTS<br/>Existence Check]
A --> G[Correlated Subqueries<br/>Citation Format]
1. O que você vai aprender
- Consulta indexada (retorna um único valor)
- Consulta baseada em coluna (retorna uma única coluna)
- Consulta baseada em linha (retorna uma linha)
- Subconsulta de tabela (retorna uma tabela)
- EXISTE/NÃO EXISTE
2. Cenários da vida real
(1) Desafio: Não é possível alcançar isso em uma única etapa
Para identificar “funcionários cujos salários são superiores ao salário médio”, é preciso calcular primeiro a média e, em seguida, fazer a comparação.
(2) Soluções para subconsultas
SELECT * FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
3. Consulta quântica padrão
Retorna uma única linha e uma única coluna.
▶ Exemplo: Consulta com tags
-- Employees with above-average salaries
SELECT * FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
-- The highest-paid employee
SELECT * FROM employees
WHERE salary = (SELECT MAX(salary) FROM employees);
-- Customers with the most recent orders
SELECT * FROM customers
WHERE id = (SELECT customer_id FROM orders ORDER BY order_date DESC LIMIT 1);
4. Questões sobre o Livro de Liezi
Retorna uma única coluna com várias linhas. É usado em conjunto com IN, NOT IN, ANY e ALL.
▶ Exemplo: Subconsulta IN
-- Customers with orders
SELECT * FROM customers
WHERE id IN (SELECT DISTINCT customer_id FROM orders);
-- Customers with no orders
SELECT * FROM customers
WHERE id NOT IN (SELECT DISTINCT customer_id FROM orders WHERE customer_id IS NOT NULL);
▶ Exemplo: subconsultas ANY/ALL
-- Salary higher than Sales Any employee in the department(Higher than the minimum)
SELECT * FROM employees
WHERE salary > ANY (SELECT salary FROM employees WHERE department = 'Sales');
-- Salary higher than Sales All employees in the department(Higher than the highest)
SELECT * FROM employees
WHERE salary > ALL (SELECT salary FROM employees WHERE department = 'Sales');
5. Subconsulta EXISTS
Verifique se a subconsulta retorna algum resultado.
▶ Exemplo: EXISTS
-- Customers with orders
SELECT * FROM customers c
WHERE EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.id);
-- Customers with no orders
SELECT * FROM customers c
WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.id);
(1) Comparação entre EXISTS e IN
| Dimensão | EXISTS | IN |
|---|---|---|
| Método de execução | Verificação linha por linha da subconsulta em relação à tabela | Executar primeiro a subconsulta e, em seguida, realizar a comparação |
| Casos de uso | Tabela externa pequena, subconsulta grande | Tabela externa grande, subconsulta pequena |
| Tratamento de valores NULL | Segurança | A armadilha do “NOT IN” com NULL |
| Desempenho | Geralmente melhor | Melhor quando o conjunto de resultados da subconsulta é pequeno |
6. Consultas a subtabelas (tabelas derivadas)
Subconsultas como tabelas temporárias.
▶ Exemplo: Subconsulta FROM
-- The highest-paid person in each department
SELECT e.* FROM employees e
INNER JOIN (
SELECT department, MAX(salary) AS max_salary
FROM employees
GROUP BY department
) dept_max ON e.department = dept_max.department AND e.salary = dept_max.max_salary;
-- Customer Order Statistics
SELECT c.name, order_stats.total_orders, order_stats.total_amount
FROM customers c
INNER JOIN (
SELECT customer_id, COUNT(*) AS total_orders, SUM(amount) AS total_amount
FROM orders
GROUP BY customer_id
) order_stats ON c.id = order_stats.customer_id;
7. Subconsultas correlacionadas
A subconsulta faz referência a campos da tabela externa.
▶ Exemplo: Subconsultas correlacionadas
-- The highest-paid employee in each department
SELECT * FROM employees e1
WHERE salary = (
SELECT MAX(salary) FROM employees e2
WHERE e2.department = e1.department
);
-- Employees whose salaries are higher than the department average
SELECT * FROM employees e1
WHERE salary > (
SELECT AVG(salary) FROM employees e2
WHERE e2.department = e1.department
);
8. Otimização de subconsultas
| Estratégia | Descrição |
|---|---|
| Use JOINs em vez de subconsultas | O otimizador do MySQL geralmente consegue lidar com isso, mas os JOINs são mais intuitivos |
| Use EXISTS em vez de IN | O EXISTS costuma ser mais rápido ao lidar com grandes conjuntos de dados |
| Evite subconsultas correlacionadas | Reescreva como um JOIN sempre que possível |
| Indexação de subconsultas | Indexação de campos de junção/filtro em subconsultas |
❓ Perguntas Frequentes
P: O que é mais rápido: uma subconsulta ou um JOIN? R: Geralmente, um JOIN é mais rápido (o otimizador consegue otimizá-lo melhor). No entanto, isso depende da distribuição dos dados; use o EXPLAIN para comparar.
P: Quantos níveis de subconsultas podem ser aninhados? R: O MySQL limita a profundidade de aninhamento (normalmente 255 níveis), mas, em geral, recomenda-se não ultrapassar 3 níveis.
P: Existe uma armadilha com NULL ao usar NOT IN? R: Sim.
NOT IN (1, 2, NULL)sempre retorna NULL. Use NOT EXISTS em vez disso.
P: O que é mais rápido: uma subconsulta ou um JOIN? R: Depende do volume de dados e dos índices; geralmente, um JOIN é mais eficiente. Recomendamos usar o EXPLAIN para comparar os planos de execução reais.
P: Quantos níveis de subconsultas podem ser aninhados? R: Teoricamente, não há limite, mas a legibilidade fica extremamente prejudicada a partir do terceiro nível; recomenda-se usar uma CTE (cláusula WITH) em vez disso.
📖 Resumo
- Consulta de quantidade padrão Retorna um único valor; compare com
= / > / < - Consulta Liezi retorna várias linhas; use
IN / NOT IN / ANY / ALL - EXISTS verifica se uma subconsulta retorna algum resultado; geralmente é mais eficiente do que IN
- Subconsulta: Utilizada na cláusula
FROMcomo uma tabela derivada - Subconsulta correlacionada faz referência a um campo de uma tabela externa e é executada uma vez para cada linha
- Princípios de otimização: Use JOIN em vez de subconsultas, use EXISTS em vez de NOT IN
📝 Exercícios
-
Problema básico (Dificuldade ⭐): Use subconsultas para identificar os funcionários cujos salários são superiores ao salário médio.
-
Problema avançado (Dificuldade: ⭐⭐): Use
EXISTSpara encontrar clientes que nunca fizeram um pedido. -
Questão desafiadora (Dificuldade: ⭐⭐⭐): Use uma subconsulta correlacionada para identificar o funcionário com o maior salário em cada departamento.