Funcoes de Agregacao
O que sao funcoes de agregacao?
Funcoes de agregacao pegam varias linhas e retornam um unico valor. Em vez de ver cada registro individualmente, voce obtem um resumo: quantos registros existem, qual a soma, a media, o menor ou o maior valor.
As cinco funcoes principais sao:
| Funcao | O que faz |
|---|---|
COUNT | Conta registros |
SUM | Soma valores |
AVG | Calcula a media |
MIN | Encontra o menor valor |
MAX | Encontra o maior valor |
COUNT -- contando registros
-- Quantos usuarios existem?
SELECT COUNT(*) FROM usuarios;
-- → 1523
-- Quantos usuarios tem telefone cadastrado?
SELECT COUNT(telefone) FROM usuarios;
-- → 1204 (ignora NULLs)
-- Quantos usuarios ativos existem?
SELECT COUNT(*) FROM usuarios WHERE status = 'ativo';
-- → 1389
-- Quantas cidades diferentes temos?
SELECT COUNT(DISTINCT cidade) FROM usuarios;
-- → 47
SUM -- somando valores
-- Valor total de todos os pedidos
SELECT SUM(valor_total) FROM pedidos;
-- → 458320.50
-- Valor total dos pedidos de janeiro
SELECT SUM(valor_total) FROM pedidos
WHERE data_criacao BETWEEN '2025-01-01' AND '2025-01-31';
-- → 52340.00
-- Total de itens em estoque
SELECT SUM(estoque) FROM produtos WHERE categoria = 'eletronicos';
-- → 3420
AVG -- calculando a media
-- Idade media dos usuarios
SELECT AVG(idade) FROM usuarios;
-- → 28.5
-- Preco medio dos produtos
SELECT AVG(preco) FROM produtos;
-- → 149.90
-- Nota media dos alunos aprovados
SELECT AVG(nota) FROM alunos WHERE nota >= 7;
-- → 8.3
-- Media arredondada com 2 casas decimais
SELECT ROUND(AVG(preco), 2) FROM produtos;
-- → 149.90
MIN e MAX -- encontrando extremos
-- Produto mais barato
SELECT MIN(preco) FROM produtos;
-- → 5.90
-- Produto mais caro
SELECT MAX(preco) FROM produtos;
-- → 4999.99
-- Usuario mais novo e mais velho
SELECT MIN(idade), MAX(idade) FROM usuarios;
-- → 16 | 72
-- Primeiro e ultimo cadastro
SELECT MIN(data_criacao), MAX(data_criacao) FROM usuarios;
-- → 2023-01-15 | 2025-03-28
-- MIN e MAX com strings (ordem alfabetica)
SELECT MIN(nome), MAX(nome) FROM usuarios;
-- → Abel | Zuleica
Combinando funcoes de agregacao
Voce pode usar varias funcoes na mesma query:
-- Resumo completo de produtos
SELECT
COUNT(*) AS total_produtos,
SUM(estoque) AS total_estoque,
ROUND(AVG(preco), 2) AS preco_medio,
MIN(preco) AS mais_barato,
MAX(preco) AS mais_caro
FROM produtos;
-- → 150 | 8430 | 149.90 | 5.90 | 4999.99
-- Resumo de pedidos do mes
SELECT
COUNT(*) AS total_pedidos,
SUM(valor_total) AS faturamento,
ROUND(AVG(valor_total), 2) AS ticket_medio,
MIN(valor_total) AS menor_pedido,
MAX(valor_total) AS maior_pedido
FROM pedidos
WHERE data_criacao >= '2025-03-01';
Combinando com WHERE
O WHERE filtra as linhas antes da agregacao rodar:
-- Media de preco apenas de eletronicos
SELECT AVG(preco) FROM produtos WHERE categoria = 'eletronicos';
-- Total vendido por um vendedor especifico
SELECT SUM(valor_total) FROM pedidos WHERE vendedor_id = 5;
-- Quantos pedidos acima de R$100
SELECT COUNT(*) FROM pedidos WHERE valor_total > 100;
-- Estatisticas apenas de usuarios ativos
SELECT
COUNT(*) AS ativos,
ROUND(AVG(idade), 1) AS idade_media,
MIN(data_criacao) AS primeiro_cadastro
FROM usuarios
WHERE status = 'ativo';
No Prisma
// COUNT
const total = await prisma.usuario.count()
const ativos = await prisma.usuario.count({ where: { status: 'ativo' } })
// Aggregate (SUM, AVG, MIN, MAX)
const stats = await prisma.produto.aggregate({
_sum: { preco: true, estoque: true },
_avg: { preco: true },
_min: { preco: true },
_max: { preco: true },
_count: true
})
// → stats._avg.preco = 149.90
// → stats._sum.estoque = 8430
// → stats._min.preco = 5.90
// → stats._count = 150
// Aggregate com WHERE
const eletronicos = await prisma.produto.aggregate({
_avg: { preco: true },
_count: true,
where: { categoria: 'eletronicos' }
})
// COUNT DISTINCT (via groupBy + contagem)
const cidadesUnicas = await prisma.usuario.groupBy({
by: ['cidade']
})
// → cidadesUnicas.length = numero de cidades distintas
No Drizzle
import { count, sum, avg, min, max } from 'drizzle-orm'
// COUNT
const [{ total }] = await db.select({ total: count() }).from(usuarios)
// COUNT com WHERE
const [{ ativos }] = await db.select({ ativos: count() }).from(usuarios)
.where(eq(usuarios.status, 'ativo'))
// Todas as agregacoes de uma vez
const [stats] = await db.select({
total: count(),
somaEstoque: sum(produtos.estoque),
precoMedio: avg(produtos.preco),
maisBarato: min(produtos.preco),
maisCaro: max(produtos.preco)
}).from(produtos)
// Com WHERE
const [eletronicos] = await db.select({
total: count(),
precoMedio: avg(produtos.preco)
}).from(produtos)
.where(eq(produtos.categoria, 'eletronicos'))
// COUNT DISTINCT
import { countDistinct } from 'drizzle-orm'
const [{ cidades }] = await db.select({
cidades: countDistinct(usuarios.cidade)
}).from(usuarios)
No Lucid (AdonisJS)
// COUNT
const total = await Usuario.query().count('* as total')
// → total[0].$extras.total = 1523
// Forma mais limpa com getCount
const ativos = await Usuario.query().where('status', 'ativo').getCount()
// → ativos = 1389
// SUM
const faturamento = await Pedido.query().sum('valor_total as total')
// → faturamento[0].$extras.total
// AVG
const media = await Produto.query().avg('preco as media')
// → media[0].$extras.media
// MIN e MAX
const extremos = await Produto.query()
.min('preco as mais_barato')
.max('preco as mais_caro')
// → extremos[0].$extras.mais_barato
// → extremos[0].$extras.mais_caro
// Combinando com WHERE
const statsEletronicos = await Produto.query()
.where('categoria', 'eletronicos')
.count('* as total')
.avg('preco as preco_medio')
.min('preco as mais_barato')
.max('preco as mais_caro')
// COUNT DISTINCT
const { default: Database } = await import('@adonisjs/lucid/services/db')
const cidades = await Database.from('usuarios').countDistinct('cidade as total')
Exercicios
- Escreva uma query que retorne o total de pedidos, o faturamento total e o ticket medio (valor medio por pedido).
- Encontre o produto mais caro e o mais barato de cada categoria (por enquanto, faca queries separadas -- GROUP BY vem na proxima aula).
- Calcule quantos usuarios se cadastraram em cada mes de 2025 (use WHERE para filtrar cada mes).
- Qual a diferenca entre
COUNT(*)eCOUNT(email)numa tabela onde alguns usuarios nao tem email? - Implemente um dashboard de estatisticas usando Prisma: total de usuarios, total de pedidos, faturamento total e ticket medio.
Referencias
Testa o que você leu
5 perguntas sobre esta aula. Errar aqui não custa nada - a explicação vem junto da correção.