Bora mergulhar ainda mais fundo na toca do coelho: vamos ver como usar subqueries dentro do FROM. Essa é uma das paradas que a galera de SQL mais curte, porque dá pra criar tabelas temporárias poderosas ali mesmo e reaproveitar como se fossem tabelas de verdade no banco.
Imagina que tu tá montando um relatório que precisa de cálculos, agrupamentos ou filtragens, mas não quer criar tabelas temporárias extras no servidor. E aí, faz o quê? É aí que entram as subqueries no FROM. Elas te permitem:
- Juntar ou agregar dados temporariamente antes do select principal.
- Criar conjuntos de dados estruturados "na hora".
- Reduzir o número de operações, exigindo do banco o mínimo de armazenamento de dados intermediários.
Subqueries no FROM funcionam tipo mini-tabelas que tu pode usar no select principal. É tipo montar um Lego: rápido, flexível e sem dor de cabeça :)
O básico das subqueries no FROM
Nas subqueries do FROM, a gente usa uma query pra criar uma tabela temporária (ou sub-tabela) que vira parte do select geral. Pra isso, tem três passos chave:
- Escrever a subquery dentro do
FROMentre parênteses. - Dar um alias (apelido) pra subquery.
- Usar esse alias como se fosse uma tabela normal.
Sintaxe
SELECT colunas
FROM (
SELECT colunas
FROM tabela
WHERE condicao
) AS apelido
WHERE condicao_externa;
Parece complicado? Bora ver uns exemplos.
Exemplo: Estudantes e média das notas
Imagina que temos duas tabelas:
students (dados dos estudantes — nome e ID):
| student_id | student_name |
|---|---|
| 1 | Alex |
| 2 | Anna |
| 3 | Dan |
grades (dados das notas dos estudantes):
| grade_id | student_id | grade |
|---|---|---|
| 1 | 1 | 80 |
| 2 | 1 | 85 |
| 3 | 2 | 90 |
| 4 | 3 | 70 |
| 5 | 3 | 75 |
Agora o desafio: pegar a lista dos estudantes e a média das notas deles.
A gente pode começar com uma subquery simples que calcula a média de cada estudante e depois usar isso no select principal.
SELECT s.student_name, g.avg_grade
FROM (
SELECT student_id, AVG(grade) AS avg_grade
FROM grades
GROUP BY student_id
) AS g
JOIN students AS s ON s.student_id = g.student_id;
Resultado:
| student_name | avg_grade |
|---|---|
| Alex | 82.5 |
| Anna | 90.0 |
| Dan | 72.5 |
Tabelas temporárias "na hora"
Subqueries no FROM são top quando tu precisa de mais de um nível de processamento nos dados. Tipo, se tu quiser não só pegar a média, mas também calcular a nota máxima de cada estudante — tudo num select só.
SELECT g.student_id, g.avg_grade, g.max_grade
FROM (
SELECT student_id,
AVG(grade) AS avg_grade,
MAX(grade) AS max_grade
FROM grades
GROUP BY student_id
) AS g;
Resultado:
| student_id | avg_grade | max_grade |
|---|---|---|
| 1 | 82.5 | 85 |
| 2 | 90 | 90 |
| 3 | 72.5 | 75 |
Repara que isso funciona como uma tabela temporária de verdade, com colunas tipo avg_grade e max_grade.
Quando usar subqueries no FROM?
Pra dados agregados. Se tu quer primeiro fazer contas (tipo média, soma ou máximo) e depois juntar com outras tabelas.
Pra filtrar dados. Quando precisa filtrar antes de juntar com a tabela principal.
Pra simplificar queries complexas. Dividir tarefas difíceis em etapas ajuda a não se perder.
Exemplo: Relatório de estudantes com dois níveis de processamento
Imagina que queremos achar estudantes com média acima de 80. A gente começa com uma subquery que calcula as médias e depois usa isso no filtro.
SELECT s.student_name, g.avg_grade
FROM students AS s
JOIN (
SELECT student_id, AVG(grade) AS avg_grade
FROM grades
GROUP BY student_id
) AS g ON s.student_id = g.student_id
WHERE g.avg_grade > 80;
Resultado:
| student_name | avg_grade |
|---|---|
| Alex | 82.5 |
| Anna | 90.0 |
Dicas e pegadinhas
Alias obrigatório. Sempre dá um alias pra subquery (tipo AS g), senão o PostgreSQL não vai saber como chamar essa "tabela temporária".
Otimização. Subqueries no FROM podem ser mais lentas que JOINs, principalmente se tu filtrar dados dentro da subquery.
Indexação. Garante que os campos usados pra join, índices e filtros estejam otimizados — isso faz muita diferença na performance.
Exemplo de query mais cabulosa: cursos e quantidade de estudantes
Agora bora pra um desafio mais real. Imagina que temos essa tabela:
courses (lista de cursos):
| course_id | course_name |
|---|---|
| 1 | SQL Basics |
| 2 | Python Basics |
E enrollments (matrículas dos estudantes nos cursos):
| student_id | course_id |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
Agora queremos saber quantos estudantes estão matriculados em cada curso.
SELECT c.course_name, e.students_count
FROM courses AS c
JOIN (
SELECT course_id, COUNT(student_id) AS students_count
FROM enrollments
GROUP BY course_id
) AS e ON c.course_id = e.course_id;
Resultado:
| course_name | students_count |
|---|---|
| SQL Basics | 2 |
| Python Basics | 1 |
Espero que tu tenha curtido a aula... mas a próxima vai ser ainda mais massa :)
GO TO FULL VERSION