CTEs Simples para Preparação de Dados: Exemplos e Casos Reais
Parece que você já pegou o jeito das CTEs e talvez até escreva WITH quase no automático. Hoje bora mergulhar um pouco mais fundo — e ver como usar CTE pra preparar dados em situações reais. Imagina que você vai montar um relatório ou uma query SQL mais complexa: primeiro tem que separar os ingredientes — aí sim dá pra cozinhar aquele “caldo” analítico gostoso.
CTE aqui é tipo uma ferramenta massa pra etapas intermediárias: filtragem, contagem, agregação, cálculo de médias — tudo que precisa pra preparar os dados de um jeito que faça sentido. Você pode quebrar uma query complicada em blocos lógicos fáceis de entender, cada um fazendo só uma coisa: seleciona os registros certos, calcula a média ou prepara os dados pra seleção final. Isso deixa o código mais legível, evita repetição e ainda te livra de criar tabelas temporárias se não precisar delas.
Esse jeito de usar CTE é especialmente útil quando você tá preparando dados pra relatórios, montando filtros complexos ou quer “limpar” os dados antes de processar mais. Nesse sentido, CTE vira mais que só uma técnica — é uma estratégia de montar a lógica passo a passo, sem perder o controle do que tá rolando.
Bora lá? Agora vem os exemplos.
Filtrando Dados com CTE
CTE é um jeito massa de “puxar” só os dados que você quer de uma tabela grandona, pra depois trabalhar só com o que interessa. Em vez de escrever subqueries gigantes, você filtra os dados, dá um nome pra esse passo — e depois usa o resultado como se fosse uma tabela normal.
Imagina que a gente tem uma tabela students, onde ficam as notas dos estudantes:
Tabela students
| student_id | first_name | last_name | grade |
|---|---|---|---|
| 1 | Otto | Lin | 87 |
| 2 | Maria | Chi | 92 |
| 3 | Alex | Ming | 79 |
| 4 | Anna | Song | 95 |
Vamos supor que você quer pegar só quem tirou nota acima de 85. Com CTE isso fica bem transparente:
WITH excellent_students AS (
SELECT student_id, first_name, last_name, grade
FROM students
WHERE grade > 85
)
SELECT * FROM excellent_students;
Resultado:
| student_id | first_name | last_name | grade |
|---|---|---|---|
| 1 | Otto | Lin | 87 |
| 2 | Maria | Chi | 92 |
| 4 | Anna | Song | 95 |
O que é legal aqui?
Você já separou as linhas que queria e deu um nome pra esse passo — excellent_students. Agora dá pra usar esse resultado depois: tipo juntar com outra tabela, filtrar de novo ou calcular a média das notas. Fica tudo legível, simples e não confunde, principalmente se a query for grandona.
Agregando Dados com CTE
Agora bora pra um caso onde precisa contar registros ou calcular médias. Por exemplo, temos uma tabela enrollments, que mostra em quais cursos cada estudante tá matriculado.
Tabela enrollments
| student_id | course_id |
|---|---|
| 1 | 101 |
| 2 | 102 |
| 3 | 101 |
| 4 | 103 |
| 2 | 101 |
A gente quer saber quantos estudantes tem em cada curso.
Exemplo de query:
WITH course_enrollments AS (
SELECT course_id, COUNT(student_id) AS student_count
FROM enrollments
GROUP BY course_id
)
SELECT * FROM course_enrollments;
Resultado:
| course_id | student_count |
|---|---|
| 101 | 3 |
| 102 | 1 |
| 103 | 1 |
O que importa aqui:
- A gente agrupou os dados por
course_ide contou quantos estudantes tem em cada curso. - A tabela
course_enrollmentsagora tem essa info, e dá pra usar ela pra analisar mais coisas depois.
Preparando Dados pra Relatórios
Se você precisa montar um relatório detalhado, baseado em vários passos de processamento, CTE é uma mão na roda. Dá pra dividir toda a lógica em blocos claros e sem criar tabela temporária à toa. Imagina que você tem uma tabela grades com as notas e uma tabela students com os dados dos estudantes. Precisa montar um relatório só com quem tem média acima de 80.
Tabela grades
| student_id | grade |
|---|---|
| 1 | 90 |
| 1 | 85 |
| 2 | 92 |
| 3 | 78 |
| 3 | 80 |
| 4 | 95 |
Tabela students
| student_id | first_name | last_name |
|---|---|---|
| 1 | Otto | Lin |
| 2 | Maria | Chi |
| 3 | Alex | Ming |
| 4 | Anna | Song |
Em vez de fazer uma subquery gigante, dá pra montar tudo em etapas:
WITH avg_grades AS (
SELECT student_id, AVG(grade) AS avg_grade
FROM grades
GROUP BY student_id
HAVING AVG(grade) > 80
),
students_with_grades AS (
SELECT s.student_id, s.first_name, s.last_name, ag.avg_grade
FROM students s
JOIN avg_grades ag ON s.student_id = ag.student_id
)
SELECT * FROM students_with_grades;
No primeiro passo (avg_grades) a gente calculou a média de cada estudante e já filtrou só quem mandou bem — acima de 80. No segundo (students_with_grades) juntamos esses dados com a tabela students pra pegar nome e sobrenome. O SELECT final devolve uma tabela pronta pra colar no relatório — tudo já calculado, filtrado e bonitinho.
Resultado:
| student_id | first_name | last_name | avg_grade |
|---|---|---|---|
| 1 | Otto | Lin | 87.5 |
| 2 | Maria | Chi | 92.0 |
| 4 | Anna | Song | 95.0 |
É esse tipo de abordagem que faz CTE ser tão prático: você foca na lógica e na estrutura, sem se preocupar com tarefas chatas tipo criar e apagar tabela temporária.
Calculando Métricas Mais Complexas
Às vezes rola de combinar vários dados numa query só. Por exemplo, queremos calcular pra cada curso:
- Quantos estudantes tem.
- Média das notas do curso.
Exemplo de query:
WITH course_counts AS (
SELECT course_id, COUNT(student_id) AS student_count
FROM enrollments
GROUP BY course_id
),
course_avg_grades AS (
SELECT e.course_id, AVG(g.grade) AS avg_grade
FROM enrollments e
JOIN grades g ON e.student_id = g.student_id
GROUP BY e.course_id
)
SELECT cc.course_id, cc.student_count, cag.avg_grade
FROM course_counts cc
JOIN course_avg_grades cag ON cc.course_id = cag.course_id;
Erros pra Evitar
Trabalhando com CTE, é fácil se enrolar e cometer uns erros clássicos.
O primeiro — materialização desnecessária. Se você cria CTE demais, o PostgreSQL pode guardar os resultados como tabelas temporárias, mesmo se só vai usar uma vez. Aí a query pode ficar mais lenta do que precisava.
O segundo erro — aplicar filtros do jeito errado. Se os filtros entram na ordem errada ou em etapas diferentes, o resultado pode não ser o que você queria. Tipo, pode acabar excluindo dados importantes cedo demais.
Por isso, CTE é melhor usar quando os dados passam por várias transformações seguidas — aí sim essa ferramenta mostra todo o potencial e te ajuda a escrever código limpo, claro e eficiente.
GO TO FULL VERSION