⌘K

05 – SQL no PostgreSQL: Agrupando Dados com GROUP BY, HAVING e Funções de Agregação

Last updated

No nosso último post, entendemos como o comando SELECT funciona e como filtrar linhas específicas usando o WHERE. Mas no dia a dia de Engenharia de Dados e DevOps, muitas vezes não queremos ver linhas individuais. Queremos o panorama geral.

Você não quer ver cada log de erro gerado; você quer saber quantos erros aconteceram por serviço. Você não quer ver cada deploy isolado; quer saber a soma de recursos (vCPUs e Memória) alocados por cluster.

É aqui que entram as Funções de Agregação e as cláusulas GROUP BY e HAVING. Vamos entender como extrair métricas consolidadas direto do PostgreSQL.

O que são Funções de Agregação?

Funções de agregação pegam múltiplos valores de uma coluna e os processam para retornar um único valor resumido. As mais comuns são:

  • COUNT(): Conta o número de linhas.
  • SUM(): Soma os valores de uma coluna numérica.
  • AVG(): Calcula a média geométrica dos valores.
  • MAX() e MIN(): Encontram o maior e o menor valor, respectivamente.

Se rodarmos apenas a função de agregação, ela resume a tabela inteira:

-- Descobrindo o total de memória alocada em toda a infraestrutura
SELECT SUM(memoria_gb) FROM servidores;

Subindo o nível com o GROUP BY

A mágica acontece quando queremos esse resumo dividido por categorias. É aí que entra o GROUP BY (Agrupar por). Ele diz ao Postgres: “Pegue essas milhares de linhas, separe-as em grupos baseados nesta coluna e aplique a função de agregação para cada grupo”.

Vamos a um cenário prático de monitoramento: queremos saber a quantidade de servidores e a média de vCPUs agrupadas por ambiente.

SELECT 
    ambiente, 
    COUNT(*) as total_servidores, 
    AVG(vcpus) as media_vcpus
FROM servidores
GROUP BY ambiente;

Regra de Ouro do GROUP BY

Existe um erro clássico que todo iniciante comete. Se você colocou uma coluna no seu SELECT (fora das funções de agregação), você obrigatoriamente precisa listá-la na cláusula GROUP BY. No exemplo acima, como selecionamos ambiente, fomos obrigados a agrupar por ambiente.

Filtrando Grupos com o HAVING

Imagine que você quer filtrar o resultado do agrupamento anterior, exibindo apenas os ambientes que possuem mais de 5 servidores cadastrados.

O seu primeiro impulso pode ser tentar usar o WHERE COUNT(*) > 5. Mas isso vai falhar.

Lembra da ordem de execução que vimos no post passado? O WHERE é executado antes do banco saber o que é um grupo. Ele filtra linhas individuais. Para filtrar grupos após a agregação, usamos o HAVING.

A ordem lógica na mente do Postgres fica assim:

  1. FROM: Abre a tabela.
  2. WHERE: Filtra as linhas individuais (ex: remove servidores inativos).
  3. GROUP BY: Agrupa o que sobrou.
  4. HAVING: Filtra os grupos baseando-se no resultado da agregação.
  5. SELECT: Mostra o resultado na tela.

Olha como fica a query em ação:

SELECT 
    ambiente, 
    COUNT(*) as total_servidores
FROM servidores
WHERE status = 'ativo'
GROUP BY ambiente
HAVING COUNT(*) > 5;

Exemplo Real: Análise de Logs de Erro

Para fechar, um exemplo típico de um pipeline de observabilidade em DevOps. Queremos identificar quais serviços da nossa arquitetura geraram mais de 100 erros críticos hoje:

SELECT 
    nome_servico, 
    COUNT(*) as total_erros
FROM logs_aplicacao
WHERE criticidade = 'CRITICAL' AND criado_em >= NOW() - INTERVAL '1 day'
GROUP BY nome_servico
HAVING COUNT(*) > 100
ORDER BY total_erros DESC;

Conclusão

Dominar o GROUP BY e o HAVING transforma o banco de dados em uma ferramenta de analytics poderosa, poupando sua aplicação de ter que baixar milhões de registros para fazer contas na memória do backend.

Porém, conforme suas queries ficam mais complexas e o volume de dados cresce, você vai perceber que o banco pode começar a demorar para responder. Como resolver isso?

No próximo post, vamos entrar em um dos temas mais vitais para a sobrevivência de um banco de dados em produção: Índices (Indexes). Vamos entender como acelerar suas buscas de minutos para milissegundos sem gastar um centavo a mais de infraestrutura. Fique ligado!

Ficou clara a diferença de quando usar o WHERE e quando usar o HAVING? Deixe sua dúvida ou sua experiência com otimização de relatórios aqui nos comentários!

Still stuck? How can we help? Get Help