Agregações: COUNT, GROUP BY, HAVING
Transformar várias linhas num resumo — "quantos pedidos por usuário", "faturamento por mês".
Funções de agregação — resumem várias linhas num valor
SELECT COUNT(*) FROM pedidos; -- quantas linhas existem
SELECT SUM(total) FROM pedidos; -- soma de todos os totais
SELECT AVG(total) FROM pedidos; -- média
SELECT MAX(total), MIN(total) FROM pedidos; -- maior e menorGROUP BY — agrupar antes de agregar
Sozinho, COUNT(*) conta TODAS as linhas. Com GROUP BY, ele conta por grupo — "quantos pedidos CADA usuário fez", não o total geral.
SQL
SELECT usuario_id, COUNT(*) AS total_pedidos
FROM pedidos
GROUP BY usuario_id;Regra prática: toda coluna no SELECT que não está dentro de uma função de agregação precisa estar no GROUP BY — o banco precisa saber "por qual coluna estou agrupando" pra cada valor que aparece solto.
HAVING — filtrar DEPOIS de agrupar
WHERE filtra linhas antes de agrupar; HAVING filtra grupos depois — por isso HAVING pode usar o resultado de uma agregação, e WHERE não pode.
SQL — só usuários com mais de 1 pedido
SELECT usuario_id, COUNT(*) AS total_pedidos
FROM pedidos
GROUP BY usuario_id
HAVING COUNT(*) > 1;-- ERRADO — WHERE não pode usar COUNT(*)
SELECT usuario_id, COUNT(*) FROM pedidos WHERE COUNT(*) > 1 GROUP BY usuario_id;
-- Error: aggregate functions are not allowed in WHERECombinando com JOIN
SQL — faturamento por usuário, só nome (via JOIN)
SELECT usuarios.nome, SUM(pedidos.total) AS total_gasto
FROM pedidos
JOIN usuarios ON pedidos.usuario_id = usuarios.id
GROUP BY usuarios.nome
ORDER BY total_gasto DESC;Exercício
Escreva a consulta que mostra a categoria de produto e a média de preço, só das categorias com mais de 3 produtos.