SQL (Structured Query Language) é a linguagem padrão para gerenciar e manipular bancos de dados relacionais. Ela permite realizar operações fundamentais como consultar (SELECT), inserir (INSERT), atualizar (UPDATE) e deletar (DELETE) dados. SQL nos dá uma forma de organizar as informações em tabelas compostas por linhas e colunas, onde cada linha representa um registro e cada coluna um atributo específico. Sua sintaxe declarativa permite que nós administradores de banco de dados, desenvolvedores e analistas especifiquemos o que desejamos obter de dados, sem nos preocuparmos em como o sistema irá executar a operação internamente.
O que são Subqueries e Por Que Utilizá-las
Subqueries, também conhecidas como consultas aninhadas, são consultas executadas dentro de outra consulta principal. Elas funcionam como uma ferramenta poderosa para resolver problemas complexos dividindo-os em partes menores e mais gerenciáveis. Uma subquery pode retornar um único valor, uma lista de valores ou até mesmo uma tabela completa, dependendo de como é estruturada. O principal benefício é permitir comparações dinâmicas e filtragens baseadas em resultados de outras consultas, eliminando a necessidade de múltiplas consultas separadas.
-- Exemplo básico: encontrar funcionários com salário acima da média
SELECT nome, salario
FROM funcionarios
WHERE salario > (
SELECT AVG(salario)
FROM funcionarios
);
Tipos de Subqueries: Escalares, de Múltiplas Linhas e Correlacionadas
Existem três tipos principais de subqueries, cada uma adequada para cenários específicos. As subqueries escalares retornam apenas um valor e são frequentemente usadas em comparações diretas. As subqueries de múltiplas linhas retornam vários valores e utilizam operadores como IN, ANY ou ALL. Já as subqueries correlacionadas fazem referência a colunas da consulta externa, sendo executadas uma vez para cada linha da consulta principal, tornando-as mais lentas mas extremamente úteis para comparações linha por linha.
-- Subquery escalar
SELECT produto_nome, preco
FROM produtos
WHERE preco = (SELECT MAX(preco) FROM produtos);
-- Subquery de múltiplas linhas
SELECT cliente_nome
FROM clientes
WHERE cidade IN (
SELECT cidade
FROM fornecedores
WHERE pais = 'Brasil'
);
-- Subquery correlacionada
SELECT e1.nome, e1.salario
FROM funcionarios e1
WHERE e1.salario > (
SELECT AVG(e2.salario)
FROM funcionarios e2
WHERE e2.departamento = e1.departamento
);
Subqueries em Diferentes Cláusulas: WHERE, FROM e SELECT
Podemos utilizá-las em várias partes de uma consulta SQL, cada posição oferecendo funcionalidades distintas. Na cláusula WHERE, queries são usadas para filtrar registros com base em condições dinâmicas. Na cláusula FROM, conhecidas como tabelas derivadas, elas criam conjuntos de dados temporários que podem ser consultados como uma tabela normal. Na cláusula SELECT, elas permitem calcular valores adicionais para cada linha do resultado principal.
-- Subquery na cláusula WHERE
SELECT pedido_id, cliente_id, total
FROM pedidos
WHERE total > (
SELECT AVG(total) * 1.5
FROM pedidos
);
-- Subquery na cláusula FROM (tabela derivada)
SELECT categoria, media_preco
FROM (
SELECT categoria, AVG(preco) as media_preco
FROM produtos
GROUP BY categoria
) as precos_categoria
WHERE media_preco > 100;
-- Subquery na cláusula SELECT
SELECT
cliente_nome,
(SELECT COUNT(*)
FROM pedidos p
WHERE p.cliente_id = c.cliente_id) as total_pedidos
FROM clientes c;
Boas Práticas e Considerações de Performance
Embora subqueries sejam úteis, é crucial utilizá-las com consciência sobre performance e legibilidade. Correlacionadas podem ser lentas em grandes volumes de dados, sendo frequentemente otimizáveis através de JOINs. Sempre considere usar índices nas colunas referenciadas pelas subqueries, e evitar desnecessariamente tornar complexo consultas que podem ser simplificadas. Para melhor manutenção, utilize CTEs (Common Table Expressions) quando a subquery for reutilizada ou muito complexa. Lembre-se também de testar a performance comparando com abordagens alternativas como JOINs ou window functions.
-- Exemplo otimizado: substituindo subquery correlacionada por JOIN
-- Versão com subquery (mais lenta)
SELECT d.nome_departamento
FROM departamentos d
WHERE EXISTS (
SELECT 1 FROM funcionarios f
WHERE f.departamento_id = d.id
AND f.salario > 5000
);
-- Versão otimizada com JOIN (mais rápida)
SELECT DISTINCT d.nome_departamento
FROM departamentos d
INNER JOIN funcionarios f ON d.id = f.departamento_id
WHERE f.salario > 5000;
-- Usando CTE para maior clareza
WITH funcionarios_alto_salario AS (
SELECT departamento_id
FROM funcionarios
WHERE salario > 5000
)
SELECT d.nome_departamento
FROM departamentos d
INNER JOIN funcionarios_alto_salario fas ON d.id = fas.departamento_id;
Deixe um comentário