O que estás a contar?
COUNT(*) conta linhas. COUNT(coluna) conta valores não nulos nessa coluna. GROUP BY define os grupos. Um total só é útil quando sabes o que representa cada linha antes e depois de um JOIN.
Filtrar grupos
HAVING permite filtrar resultados de agregação, por exemplo equipas com mais de cinco incidentes. WHERE aplica-se às linhas de entrada. Documenta também o intervalo temporal e o fuso usado numa métrica para evitar comparações incompatíveis.
Aplicação guiada no trabalho
Num fecho mensal fictício, duas encomendas distintas de 100 euros devem somar 200, mesmo que tenham o mesmo valor. Se cada uma tiver duas linhas de detalhe, somar o total após o JOIN produz 400. SUM(DISTINCT amount) produz 100, porque distingue valores e não identidades. Volta a uma linha por encomenda elegível antes da soma. Define também o período e o fuso horário: intervalos adjacentes com início incluído e fim excluído evitam contar a fronteira duas vezes. Para uma população vazia, SUM devolve NULL; converte para zero apenas quando o contrato da métrica assim o define. COUNT(*) e COUNT(coluna) respondem a perguntas diferentes. Regista a unidade, a população e os filtros junto do indicador para permitir reconciliação.
SELECT team_id, COUNT(*) AS total
FROM incidents
WHERE severity = 1
GROUP BY team_id
HAVING COUNT(*) > 5;Um indicador mensal conta ocorrências, não linhas de atualizações do mesmo incidente. Escolhe a entidade e a chave certas antes de publicar o número.
Armadilhas comuns
Corrigir duplicação com SUM DISTINCT; omitir o fuso ou incluir duas vezes a fronteira.
Tópicos relacionados: Alterações que preservam regras · Índices e planos de execução
Uma métrica começa pela definição da unidade contada.
Referência: PostgreSQL 18: Aggregate functions · PostgreSQL 18 reference semantics; DR SQL 2026.4; synthetic plan metrics and portable SQLite 3.51.2 examples