De primeira, funções window e funções agregadas parecem ferramentas parecidas pra analisar e processar dados. Afinal, as duas fazem cálculos tipo soma, média, ranking e tal. Mas bora entender qual é a real diferença entre elas.
Funções agregadas (GROUP BY)
Funções agregadas funcionam assim:
- Elas agrupam as linhas pelos campos que você indicar.
- Depois de agrupar, cada grupo vira uma linha só no resultado.
- Exemplo: você quer saber o total de vendas por cada região.
SELECT region, SUM(sales) AS total_sales
FROM sales_data
GROUP BY region;
Detalhe: GROUP BY "comprime" os dados. Se você usa agrupamento, todas as linhas que fazem parte de um grupo somem — só sobra o resultado da agregação.
Funções window (PARTITION BY)
Funções window, por outro lado:
- Mantêm a estrutura original dos dados (nada de sumir ou comprimir linhas!).
- Podem fazer cálculos dentro de "janelas" — grupos lógicos de linhas.
Exemplo: você quer saber a fatia de vendas de cada cidade no total de vendas da região dela, mas sem perder nenhuma linha.
SELECT
region,
city,
sales,
SUM(sales) OVER (PARTITION BY region) AS total_sales_by_region
FROM sales_data;
Detalhe: usar funções window não apaga linhas, só adiciona novos valores calculados pra cada linha.
Exemplo: SUM() com GROUP BY vs SUM() com PARTITION BY
Pra sacar melhor a diferença, bora ver como SUM() funciona nos dois casos. Imagina que a gente tem uma tabela sales_data assim:
| region | city | sales |
|---|---|---|
| North | CityA | 100 |
| North | CityB | 150 |
| South | CityC | 200 |
| South | CityD | 250 |
Somando com GROUP BY
A gente quer saber o total de vendas por região:
SELECT region, SUM(sales) AS total_sales
FROM sales_data
GROUP BY region;
O resultado vai ser assim:
| region | total_sales |
|---|---|
| North | 250 |
| South | 450 |
O que rolou: as linhas foram agrupadas por region e cada grupo foi "comprimido" numa linha só com a soma das vendas.
Somando com PARTITION BY
Agora bora fazer a mesma coisa com função window:
SELECT
region,
city,
sales,
SUM(sales) OVER (PARTITION BY region) AS total_sales_by_region
FROM sales_data;
O resultado:
| region | city | sales | total_sales_by_region |
|---|---|---|---|
| North | CityA | 100 | 250 |
| North | CityB | 150 | 250 |
| South | CityC | 200 | 450 |
| South | CityD | 250 | 450 |
O que rolou: PARTITION BY não "comprime" as linhas. Ele só faz o cálculo da soma dentro das janelas (cada região é uma janela separada).
Quando usar GROUP BY e quando usar PARTITION BY?
GROUP BY: bom pra relatórios finais
GROUP BY é útil quando você quer reduzir o volume de dados e pegar só os resultados finais por grupo. Tipo:
- Vendas totais por mês.
- Contar quantos pedidos tem por categoria de produto.
Exemplo:
SELECT category, COUNT(*) AS total_orders
FROM orders
GROUP BY category;
PARTITION BY: perfeito pra análise detalhada
PARTITION BY é massa quando você quer manter todas as linhas e ainda calcular algo pra cada uma delas. Tipo:
- Descobrir a fatia de vendas de cada produto na categoria.
- Numerar as linhas dentro de cada grupo.
Exemplo de cálculo de porcentagem de vendas:
SELECT
category,
product,
sales,
ROUND(
(sales * 100.0) / SUM(sales) OVER (PARTITION BY category),
2
) AS sales_percentage
FROM sales_data;
Exemplo: usando várias funções window
Uma das vantagens das funções window é poder usar vários cálculos de uma vez só. Tipo assim:
SELECT
region,
city,
sales,
SUM(sales) OVER (PARTITION BY region) AS total_sales,
RANK() OVER (PARTITION BY region ORDER BY sales DESC) AS sales_rank
FROM sales_data;
O resultado:
| region | city | sales | total_sales | sales_rank |
|---|---|---|---|---|
| North | CityB | 150 | 250 | 1 |
| North | CityA | 100 | 250 | 2 |
| South | CityD | 250 | 450 | 1 |
| South | CityC | 200 | 450 | 2 |
Vantagens das funções window sobre GROUP BY
Mantém os dados originais: GROUP BY "comprime" as linhas, mas funções window deixam a estrutura da tabela igualzinha.
Vários cálculos numa query só: Você pode usar várias funções window com PARTITION BY e ORDER BY diferentes, sem perder dados.
Análise flexível: Funções window deixam você montar cálculos do jeito que quiser: somas acumuladas, ranking, porcentagem e muito mais.
Exemplo de flexibilidade
Bora juntar várias funções:
SELECT
region,
city,
sales,
SUM(sales) OVER (PARTITION BY region) AS total_sales,
AVG(sales) OVER (PARTITION BY region) AS avg_sales,
RANK() OVER (PARTITION BY region ORDER BY sales DESC) AS rank
FROM sales_data;
O resultado:
| region | city | sales | total_sales | avg_sales | rank |
|---|---|---|---|---|---|
| North | CityB | 150 | 250 | 125.0 | 1 |
| North | CityA | 100 | 250 | 125.0 | 2 |
| South | CityD | 250 | 450 | 225.0 | 1 |
| South | CityC | 200 | 450 | 225.0 | 2 |
Limitações e erros comuns
Um erro bem comum é tentar usar PARTITION BY quando você queria mesmo era "comprimir" os dados. Tipo, ao invés de:
SELECT region, SUM(sales) AS total_sales
FROM sales_data
GROUP BY region;
Tem gente que tenta assim:
SELECT
region,
SUM(sales) OVER (PARTITION BY region) AS total_sales
FROM sales_data;
Só que isso vai trazer todas as linhas, sem reduzir o volume de dados (o que nem sempre é o que você quer).
Agora você já sabe certinho quando usar GROUP BY e quando usar funções window. É tipo escolher entre martelo e chave de fenda: os dois servem pra trabalhar com prego... mas cada um do seu jeito.
GO TO FULL VERSION