SQL GROUP BY e Funções de Agregação: Resuma Seus Dados

Published: 2026-04-08

GROUP BY colapsa múltiplas linhas que compartilham o mesmo valor em uma ou mais colunas em uma única linha de resumo. Combinado com funções de agregação como COUNT, SUM, AVG, MIN e MAX, ele é a base de quase todas as consultas de relatórios e análises. GROUP BY é suportado em todos os bancos de dados SQL, incluindo SQLite, PostgreSQL, MySQL, SQL Server e Oracle.

Dados de Exemplo

Usamos duas tabelas em todos os exemplos:

Tabela employees:

id name department hire_date salary
1 Alice Engineering 2023-01-15 95000
2 Bob Engineering 2023-06-01 85000
3 Carol Engineering 2024-03-10 85000
4 Dave Sales 2023-02-20 72000
5 Eve Sales 2023-09-05 68000
6 Frank Sales 2024-01-15 65000
7 Grace Marketing 2023-04-01 82000
8 Henry Marketing 2024-06-01 70000

Tabela orders:

id customer product category quantity unit_price order_date status
1 Acme Corp Laptop Pro Electronics 3 1299.99 2026-01-05 delivered
2 Acme Corp Wireless Mouse Electronics 10 29.99 2026-01-12 delivered
3 Globex Office Chair Furniture 5 249.99 2026-01-18 delivered
4 Globex Standing Desk Furniture 2 599.99 2026-01-20 shipped
5 Initech Notebook Pack Stationery 20 12.99 2026-02-03 delivered
6 Initech Pen Set Stationery 15 8.99 2026-02-07 delivered
7 Acme Corp Monitor 27" Electronics 4 399.99 2026-02-14 delivered
8 Umbrella Ltd Laptop Pro Electronics 2 1299.99 2026-02-20 cancelled
9 Umbrella Ltd Desk Lamp Furniture 8 39.99 2026-03-01 delivered
10 Globex Wireless Mouse Electronics 12 29.99 2026-03-05 shipped
11 Initech Monitor 27" Electronics 1 399.99 2026-03-10 delivered
12 Acme Corp Standing Desk Furniture 1 599.99 2026-03-15 processing
Explore o conjunto de dados no DbGate Lite

Sintaxe de GROUP BY

SELECT column1, aggregate_function(column2)
FROM table_name
WHERE condition
GROUP BY column1
HAVING aggregate_condition
ORDER BY column1;
  • GROUP BY — uma ou mais colunas cujas combinações de valores distintos definem cada grupo
  • Funções de agregação — calculam um único valor a partir de todas as linhas do grupo
  • HAVING — filtra grupos (como WHERE, mas para resultados agrupados)
  • Toda coluna em SELECT que não estiver dentro de uma agregação deve aparecer em GROUP BY

Ordem de Execução do SQL

As cláusulas SQL são escritas em uma ordem, mas executadas em outra. Entender isso ajuda a explicar por que HAVING pode referenciar funções de agregação, mas WHERE não, e por que você não pode usar um alias de SELECT em uma cláusula HAVING.

FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
Etapa Cláusula O que acontece
1 FROM Carrega a(s) tabela(s) e avalia quaisquer JOINs
2 WHERE Filtra linhas individuais — funções de agregação não são permitidas aqui
3 GROUP BY Colapsa as linhas restantes em grupos
4 HAVING Filtra grupos — funções de agregação são permitidas aqui
5 SELECT Calcula colunas de saída e aliases
6 ORDER BY Ordena o conjunto de resultados final

É por isso que WHERE status = 'delivered' é executado antes do agrupamento (rápido, filtro em nível de linha), enquanto HAVING COUNT(*) > 2 é executado após o agrupamento (filtra grupos inteiros).

COUNT()

COUNT(*) conta todas as linhas em um grupo. COUNT(column) conta valores não nulos nessa coluna.

Exemplo: Número de Funcionários por Departamento

Exemplo: Número de Pedidos por Cliente

Exemplo: Contar Entregues vs. Outros Status

Conte apenas pedidos que correspondem a uma condição usando COUNT com uma expressão CASE:

SUM()

SUM(column) soma todos os valores no grupo para uma coluna numérica.

Exemplo: Salário Total por Departamento

Exemplo: Receita Total por Categoria

Calcule a receita como quantity * unit_price:

Exemplo: Receita por Cliente e Categoria

Agrupe por múltiplas colunas para detalhar ainda mais a receita:

AVG()

AVG(column) retorna a média aritmética de todos os valores não nulos no grupo.

Exemplo: Salário Médio por Departamento

Exemplo: Valor Médio de Pedido por Cliente

MIN() e MAX()

MIN(column) e MAX(column) retornam os menores e maiores valores no grupo.

Exemplo: Faixa Salarial por Departamento

Exemplo: Primeira e Última Data de Pedido por Cliente

Combinando Múltiplas Agregações

Você pode combinar qualquer número de funções de agregação em uma única consulta.

Exemplo: Resumo Completo do Departamento

Exemplo: Resumo de Pedidos por Cliente

HAVING

HAVING filtra grupos após a agregação — é o equivalente a WHERE para resultados agrupados.

Exemplo: Departamentos com Mais de Dois Funcionários

Exemplo: Clientes com Receita Total Acima de 2000

Exemplo: Categorias com Valor Médio de Pedido Abaixo de 500

WHERE vs. HAVING

WHERE filtra linhas individuais antes do agrupamento. HAVING filtra grupos após a agregação.

Exemplo: Receita Apenas de Pedidos Entregues por Cliente

Use WHERE para excluir linhas antes do agrupamento e depois HAVING para filtrar resultados:

GROUP BY com JOINs

Você pode agrupar dados que abrangem múltiplas tabelas fazendo JOIN primeiro.

Exemplo: Receita por Departamento via Join com Employee

Exemplo: Contagem de Pedidos e Receita por Categoria e Mês

GROUP BY com Expressões

Você pode agrupar por expressões calculadas, não apenas por colunas simples.

Exemplo: Funcionários Contratados por Ano

Exemplo: Pedidos por Mês

COUNT(DISTINCT)

COUNT(DISTINCT column) conta o número de valores únicos no grupo.

Exemplo: Produtos Únicos Pedidos por Cliente

Filtrando Grupos com Múltiplas Condições

HAVING suporta qualquer expressão booleana, incluindo combinações AND/OR.

Exemplo: Clientes Ativos de Alto Valor

Encontre clientes com mais de um pedido e receita total acima de 1000:

Exemplo Prático: Relatório de Vendas

Combine tudo em um relatório completo de resumo de vendas.

Exemplo: Relatório de Desempenho por Categoria

Exemplo: Produto com Maior Receita

GROUP BY vs. Funções de Janela

GROUP BY colapsa linhas em uma linha por grupo. Funções de janela mantêm todas as linhas e adicionam uma coluna calculada — veja o tutorial de Funções de Janela em SQL para detalhes.

Exemplo: GROUP BY Retorna Uma Linha por Departamento

Exemplo: Função de Janela Mantém Todas as Linhas

Casos de Uso Comuns para GROUP BY

  • Painéis de relatórios — Resumir totais, médias e contagens por categoria ou período de tempo
  • Análise de headcount — Contar funcionários, usuários ou registros por grupo
  • Detalhamento de receita — Receita total e média por produto, região ou cliente
  • Análise de tendências — Agrupar por mês ou ano para identificar padrões ao longo do tempo
  • Top-N por grupo — Combinar com subconsultas ou CTEs para encontrar o melhor desempenho em cada grupo
  • Validação de dados — Contar duplicatas ou valores NULL entre grupos
  • Análise de coorte — Agrupar usuários por data de cadastro ou segmento de comportamento

Dicas de Desempenho

  1. Indexe colunas de GROUP BY — Índices nas colunas agrupadas aceleram a etapa de ordenação e agrupamento
  2. Filtre cedo com WHERE — Reduzir linhas antes do agrupamento com WHERE é mais rápido do que filtrar depois com HAVING
  3. Evite SELECT * — Selecione apenas as colunas de que você realmente precisa; operações de agregação se beneficiam de dados mais estreitos
  4. Use índices abrangentes (covering indexes) — Um índice que inclui tanto a coluna de GROUP BY quanto a coluna agregada pode evitar um full table scan
  5. Considere views materializadas — Para agregações frequentemente calculadas em grandes tabelas, alguns bancos de dados suportam resumos pré-computados

Resumo

  • GROUP BY colapsa linhas que compartilham os mesmos valores de coluna em uma linha de resumo por combinação única
  • COUNT(*) conta todas as linhas; COUNT(column) conta valores não nulos; COUNT(DISTINCT column) conta valores únicos
  • SUM totaliza valores numéricos; AVG calcula a média; MIN / MAX encontram os limites
  • Toda coluna em SELECT deve aparecer em GROUP BY ou estar envolvida em uma função de agregação
  • WHERE filtra linhas antes do agrupamento; HAVING filtra grupos após a agregação
  • Você pode usar GROUP BY em expressões (por exemplo, SUBSTR(date, 1, 7) para agrupamento em nível de mês)
  • Fazer JOIN entre tabelas antes de agrupar permite combinar dados de múltiplas fontes em um único relatório
  • Use funções de janela em vez de GROUP BY quando precisar de métricas em nível de grupo sem perder as linhas individuais

Tente combinar GROUP BY com JOINs, expressões CASE e cláusulas HAVING para construir os relatórios de que sua análise de dados precisa!