As subconsultas são consideradas um dos tópicos mais avançados em SQL. Reserve tempo extra para estudar este conteúdo e pratique bastante!
Para acompanhar todos os exemplos desta aula, execute o script abaixo no seu banco de dados:
Execute este script no seu SGBD (MySQL, PostgreSQL, SQLite, etc.) para criar a estrutura completa:
-- ============================================
-- SCRIPT COMPLETO PARA AULA DE SUBCONSULTAS
-- ============================================
-- 1. Criação da tabela ALUNOS
CREATE TABLE alunos (
id INTEGER PRIMARY KEY,
nome VARCHAR(100) NOT NULL,
idade INTEGER NOT NULL,
curso VARCHAR(50) NOT NULL,
turma VARCHAR(10) NOT NULL,
cidade VARCHAR(50) NOT NULL,
nota_media DECIMAL(4,2) NOT NULL,
data_matricula DATE,
ativo BOOLEAN DEFAULT TRUE
);
-- 2. Criação da tabela CURSOS
CREATE TABLE cursos (
id INTEGER PRIMARY KEY,
nome_curso VARCHAR(50) NOT NULL,
carga_horaria INTEGER NOT NULL,
coordenador VARCHAR(100) NOT NULL,
modalidade VARCHAR(20) DEFAULT 'Presencial'
);
-- 3. Criação da tabela PROFESSORES
CREATE TABLE professores (
id INTEGER PRIMARY KEY,
nome VARCHAR(100) NOT NULL,
especialidade VARCHAR(50) NOT NULL,
salario DECIMAL(10,2),
data_contratacao DATE
);
-- 4. Inserção de dados na tabela ALUNOS
INSERT INTO alunos (id, nome, idade, curso, turma, cidade, nota_media, data_matricula, ativo) VALUES
(1, 'Ana Clara Silva', 17, 'Informática', 'A', 'Garanhuns', 8.5, '2024-01-15', TRUE),
(2, 'Bruno Silva Santos', 18, 'Logística', 'A', 'Caetés', 7.2, '2024-01-20', TRUE),
(3, 'Carlos Eduardo Lima', 19, 'Informática', 'B', 'Garanhuns', 9.1, '2024-02-01', TRUE),
(4, 'Daniela Lima Costa', 17, 'Logística', 'B', 'Capoeiras', 6.8, '2024-02-05', TRUE),
(5, 'Eduarda Souza Oliveira', 18, 'Informática', 'A', 'Garanhuns', 8.9, '2024-02-10', TRUE),
(6, 'Felipe Costa Pereira', 16, 'Logística', 'C', 'Paranatama', 7.5, '2024-02-15', TRUE),
(7, 'Gabriela Ramos Santos', 17, 'Informática', 'C', 'Garanhuns', 9.3, '2024-02-20', TRUE),
(8, 'Henrique Melo Silva', 20, 'Logística', 'A', 'Caetés', 6.2, '2024-03-01', TRUE),
(9, 'Isabela Nunes Costa', 18, 'Informática', 'B', 'Correntes', 8.7, '2024-03-05', TRUE),
(10, 'João Pedro Almeida', 17, 'Logística', 'C', 'Garanhuns', 7.8, '2024-03-10', TRUE),
(11, 'Karla Mendes Silva', 19, 'Informática', 'A', 'Garanhuns', 7.1, '2024-03-15', TRUE),
(12, 'Lucas Ferreira Costa', 18, 'Logística', 'B', 'Caetés', 8.3, '2024-03-20', TRUE);
-- 5. Inserção de dados na tabela CURSOS
INSERT INTO cursos (id, nome_curso, carga_horaria, coordenador, modalidade) VALUES
(1, 'Informática', 1200, 'Prof. Silva', 'Presencial'),
(2, 'Logística', 1000, 'Prof. Santos', 'Presencial'),
(3, 'Administração', 800, 'Prof. Costa', 'EAD');
-- 6. Inserção de dados na tabela PROFESSORES
INSERT INTO professores (id, nome, especialidade, salario, data_contratacao) VALUES
(1, 'Prof. Silva', 'Programação', 5000.00, '2020-01-15'),
(2, 'Prof. Santos', 'Gestão', 4500.00, '2020-02-01'),
(3, 'Prof. Costa', 'Administração', 4200.00, '2020-03-01');
-- 7. Verificação dos dados inseridos
SELECT 'Dados inseridos com sucesso!' AS status;
SELECT COUNT(*) AS total_alunos FROM alunos;
SELECT COUNT(*) AS total_cursos FROM cursos;
SELECT COUNT(*) AS total_professores FROM professores;
Após executar o script, você deve ter 12 alunos, 3 cursos e 3 professores cadastrados. Todos os exemplos desta aula usarão estes dados!
As subconsultas são o coração do SQL avançado. Elas permitem resolver problemas complexos que seriam impossíveis com consultas simples, tornando você um desenvolvedor SQL muito mais poderoso!
Uma subconsulta (ou subquery) é uma consulta SQL que está aninhada dentro de outra consulta. Ela é executada primeiro e seu resultado é usado pela consulta externa (principal).
-- Estrutura básica de uma subconsulta
SELECT coluna1, coluna2
FROM tabela1
WHERE coluna1 IN (
SELECT coluna
FROM tabela2
WHERE condição
);
Cenário: Encontrar todos os alunos que têm idade maior que a média de idade de todos os alunos.
-- Subconsulta escalar (retorna um único valor)
SELECT nome, idade
FROM alunos
WHERE idade > (SELECT AVG(idade) FROM alunos);
(SELECT AVG(idade) FROM alunos) calcula a média de idadeVídeo: Introdução às Subconsultas em SQL - Curso em Vídeo (10 minutos)
As subconsultas são classificadas por tipo de retorno e relacionamento com a consulta externa. Entender essas diferenças é crucial!
Definição: Retornam um único valor (uma linha, uma coluna). Podem ser usadas em comparações diretas.
-- Encontrar alunos com idade maior que a média
SELECT nome, idade
FROM alunos
WHERE idade > (SELECT AVG(idade) FROM alunos);
Como funciona: A subconsulta (SELECT AVG(idade) FROM alunos) retorna um único número (a média), que é usado na comparação.
Definição: Retornam uma lista de valores. Usadas com operadores como IN, NOT IN, ANY, ALL.
-- Encontrar alunos de cursos que têm mais de 3 estudantes
SELECT nome, curso
FROM alunos
WHERE curso IN (
SELECT curso
FROM alunos
GROUP BY curso
HAVING COUNT(*) > 3
);
Como funciona: A subconsulta retorna uma lista de cursos, e o IN verifica se o curso do aluno está nessa lista.
Definição: Referenciam colunas da consulta externa. Executadas para cada linha da consulta principal.
-- Encontrar o melhor aluno de cada curso
SELECT a.nome, a.curso, a.nota_media
FROM alunos a
WHERE a.nota_media = (
SELECT MAX(nota_media)
FROM alunos b
WHERE b.curso = a.curso
);
Como funciona: Para cada aluno, a subconsulta calcula a maior nota do seu curso. Se a nota do aluno for igual à maior nota, ele é selecionado.
| Tipo | Retorna | Execuções | Complexidade | Uso Comum |
|---|---|---|---|---|
| Escalar | 1 valor | 1 vez | Baixa | Comparações simples |
| Lista | Múltiplos valores | 1 vez | Média | Filtros com IN/NOT IN |
| Correlacionada | 1 valor por linha | N vezes | Alta | Análises por grupo |
Vídeo: Subconsultas em SQL - Tipos e Exemplos Práticos (15 minutos)
As subconsultas correlacionadas são o nível mais avançado de SQL. Elas são poderosas, mas complexas. Domine este conceito e você será um expert em SQL!
Uma subconsulta correlacionada é aquela que referencia colunas da consulta externa. Ela é executada uma vez para cada linha da consulta principal, criando uma relação dinâmica entre as duas consultas.
Encontrar o aluno com a maior nota em cada curso.
-- Encontrar o melhor aluno de cada curso
SELECT a.nome, a.curso, a.nota_media
FROM alunos a
WHERE a.nota_media = (
SELECT MAX(nota_media)
FROM alunos b
WHERE b.curso = a.curso -- ← Esta é a correlação!
);
b.curso = a.curso cria a correlaçãoEncontrar alunos com nota acima da média do seu próprio curso.
-- Alunos com nota acima da média do seu curso
SELECT a.nome, a.curso, a.nota_media
FROM alunos a
WHERE a.nota_media > (
SELECT AVG(nota_media)
FROM alunos b
WHERE b.curso = a.curso -- ← Correlação por curso
);
Encontrar alunos que estão entre os 3 melhores do seu curso.
-- Top 3 alunos de cada curso
SELECT a.nome, a.curso, a.nota_media
FROM alunos a
WHERE (
SELECT COUNT(*)
FROM alunos b
WHERE b.curso = a.curso
AND b.nota_media > a.nota_media
) < 3; -- Menos de 3 pessoas têm nota maior
Vídeo: Subconsultas Correlacionadas - SQL Avançado (20 minutos)
| Operador | Descrição | Exemplo |
|---|---|---|
EXISTS |
Verifica se existe pelo menos um registro | WHERE EXISTS (SELECT 1 FROM tabela WHERE condição) |
NOT EXISTS |
Verifica se NÃO existe nenhum registro | WHERE NOT EXISTS (SELECT 1 FROM tabela WHERE condição) |
ANY/SOME |
Verdadeiro se qualquer valor satisfaz a condição | WHERE valor > ANY (SELECT coluna FROM tabela) |
ALL |
Verdadeiro se todos os valores satisfazem a condição | WHERE valor > ALL (SELECT coluna FROM tabela) |
Os aliases são essenciais em subconsultas complexas. Eles tornam o código mais legível e evitam ambiguidades quando há múltiplas tabelas com nomes de colunas similares.
-- Aliases de tabela (obrigatórios em subconsultas correlacionadas)
SELECT a.nome, a.curso
FROM alunos a
WHERE a.nota_media > (
SELECT AVG(b.nota_media)
FROM alunos b
WHERE b.curso = a.curso
);
-- Aliases de coluna (para resultados mais claros)
SELECT
a.nome AS "Nome do Aluno",
a.curso AS "Curso",
a.nota_media AS "Nota Média"
FROM alunos a;
Encontrar alunos com nota acima da média do seu curso, mostrando informações claras.
-- Solução com aliases claros
SELECT
a.nome AS "Nome do Aluno",
a.curso AS "Curso",
a.nota_media AS "Nota do Aluno",
(SELECT AVG(b.nota_media)
FROM alunos b
WHERE b.curso = a.curso) AS "Média do Curso"
FROM alunos a
WHERE a.nota_media > (
SELECT AVG(b.nota_media)
FROM alunos b
WHERE b.curso = a.curso
)
ORDER BY a.curso, a.nota_media DESC;
a e b distinguem as tabelasEncontrar alunos que estão entre os 3 melhores do seu curso, com informações detalhadas.
-- Ranking relativo com aliases
SELECT
a.nome AS "Nome",
a.curso AS "Curso",
a.nota_media AS "Nota",
(SELECT COUNT(*)
FROM alunos b
WHERE b.curso = a.curso
AND b.nota_media > a.nota_media) + 1 AS "Posição no Curso"
FROM alunos a
WHERE (
SELECT COUNT(*)
FROM alunos b
WHERE b.curso = a.curso
AND b.nota_media > a.nota_media
) < 3
ORDER BY a.curso, a.nota_media DESC;
Vídeo: Aliases e Boas Práticas em SQL (12 minutos)
A ordenação é fundamental para apresentar resultados de subconsultas de forma organizada e útil. Vamos ver como combinar ORDER BY com subconsultas complexas.
-- Ordenação simples
SELECT coluna1, coluna2
FROM tabela
ORDER BY coluna1 ASC, coluna2 DESC;
-- Ordenação com aliases
SELECT
nome AS "Nome",
curso AS "Curso"
FROM alunos
ORDER BY "Nome" ASC;
Encontrar os 5 melhores alunos com nota acima da média, ordenados por nota.
-- Top 5 alunos acima da média
SELECT
a.nome AS "Nome",
a.curso AS "Curso",
a.nota_media AS "Nota"
FROM alunos a
WHERE a.nota_media > (SELECT AVG(nota_media) FROM alunos)
ORDER BY a.nota_media DESC
LIMIT 5;
Alunos ordenados por curso e depois por nota (maior primeiro).
-- Ordenação por curso e nota
SELECT
a.nome AS "Nome",
a.curso AS "Curso",
a.nota_media AS "Nota"
FROM alunos a
ORDER BY a.curso ASC, a.nota_media DESC;
Alunos ordenados pela diferença entre sua nota e a média do curso.
-- Ordenação por diferença da média
SELECT
a.nome AS "Nome",
a.curso AS "Curso",
a.nota_media AS "Nota",
a.nota_media - (SELECT AVG(b.nota_media)
FROM alunos b
WHERE b.curso = a.curso) AS "Diferença da Média"
FROM alunos a
ORDER BY "Diferença da Média" DESC;
-- Ordenar por curso, mas Informática primeiro
SELECT nome, curso, nota_media
FROM alunos
ORDER BY
CASE curso
WHEN 'Informática' THEN 1
ELSE 2
END,
nota_media DESC;
-- Ordenar por posição no curso
SELECT
nome, curso, nota_media,
(SELECT COUNT(*) + 1
FROM alunos b
WHERE b.curso = a.curso
AND b.nota_media > a.nota_media) AS "Posição"
FROM alunos a
ORDER BY curso, "Posição";
Vídeo: ORDER BY e Técnicas de Ordenação em SQL (15 minutos)
Agora vamos aplicar tudo que aprendemos sobre subconsultas em exercícios práticos. Estes exercícios simulam situações reais do mercado de trabalho!
Use o seguinte script para criar as tabelas e dados de exemplo:
-- Tabela de alunos
CREATE TABLE alunos (
id INTEGER PRIMARY KEY,
nome TEXT,
idade INTEGER,
curso TEXT,
turma TEXT,
cidade TEXT,
nota_media REAL
);
-- Tabela de cursos
CREATE TABLE cursos (
id INTEGER PRIMARY KEY,
nome_curso TEXT,
carga_horaria INTEGER,
coordenador TEXT
);
-- Inserção de dados
INSERT INTO alunos (id, nome, idade, curso, turma, cidade, nota_media) VALUES
(1, 'Ana Clara', 17, 'Informática', 'A', 'Garanhuns', 8.5),
(2, 'Bruno Silva', 18, 'Logística', 'A', 'Caetés', 7.2),
(3, 'Carlos Eduardo', 19, 'Informática', 'B', 'Garanhuns', 9.1),
(4, 'Daniela Lima', 17, 'Logística', 'B', 'Capoeiras', 6.8),
(5, 'Eduarda Souza', 18, 'Informática', 'A', 'Garanhuns', 8.9),
(6, 'Felipe Costa', 16, 'Logística', 'C', 'Paranatama', 7.5),
(7, 'Gabriela Ramos', 17, 'Informática', 'C', 'Garanhuns', 9.3),
(8, 'Henrique Melo', 20, 'Logística', 'A', 'Caetés', 6.2),
(9, 'Isabela Nunes', 18, 'Informática', 'B', 'Correntes', 8.7),
(10, 'João Pedro', 17, 'Logística', 'C', 'Garanhuns', 7.8);
INSERT INTO cursos (id, nome_curso, carga_horaria, coordenador) VALUES
(1, 'Informática', 1200, 'Prof. Silva'),
(2, 'Logística', 1000, 'Prof. Santos');
Desafio: Encontre todos os alunos com nota acima da média geral da escola.
Desafio: Encontre alunos de cursos que têm mais de 4 estudantes matriculados.
Desafio: Encontre o melhor aluno de cada curso (maior nota por curso).
Desafio: Encontre alunos que estão entre os 3 melhores do seu curso.
Desafio: Encontre alunos com nota superior à média do seu próprio curso, ordenados por diferença da média.
Vídeo: Exercícios Práticos de Subconsultas - Curso em Vídeo (25 minutos)
Estes são os desafios mais complexos de subconsultas. Se você conseguir resolver estes, você domina SQL avançado!
Problema: Encontre alunos que moram em cidades onde a média de notas é superior à média geral da escola, mostrando nome, cidade, nota e média da cidade.
Problema: Para cada curso, mostre: nome do curso, número de alunos, média geral, melhor aluno, pior aluno, e quantos alunos estão acima da média do curso.
Problema: Crie um ranking completo mostrando: posição no curso, nome, curso, nota, diferença da média do curso, e percentual de alunos com nota menor.
Problema: Identifique "talentos" (alunos com nota no top 20% do seu curso) e "alunos em risco" (nota no bottom 20% do seu curso), com estatísticas detalhadas.
Problema: Crie um relatório que mostre, para cada turma: nome da turma, curso, número de alunos, média de notas, melhor aluno, pior aluno, alunos acima da média, e ranking da turma no curso.
Baixe o material completo da Semana 7 em PDF para estudo offline!
Baixar PDF Iniciar Quiz