CodeGym /Cursos /SQL SELF /Cálculo de somas acumuladas usando funções de janela:

Cálculo de somas acumuladas usando funções de janela: SUM(), AVG()

SQL SELF
Nível 29, Lição 4
Disponível

Bora imaginar: você tá acompanhando as receitas da sua empresa, vendas da sua loja online ou até só analisando seus gastos do ano. Você não quer só ver quanto ganhou ou gastou em cada mês, mas também entender como isso vai acumulando de mês em mês.

Funções agregadoras normais (GROUP BY) não vão ajudar aqui — elas agrupam os dados e devolvem uma linha por grupo. Mas e se a gente quiser ver cada mês e ao mesmo tempo calcular a soma acumulada? É aí que SUM() junto com funções de janela salva a gente.

O básico de funções de janela pra somas acumuladas

Funções de janela deixam você fazer operações agregadas em janelas. Assim, dá pra somar valores em cada linha, mas sem sumir com as outras linhas. Chega de sacrificar dados por causa do GROUP BY!

Sintaxe do SUM() com função de janela

Aqui vai um template básico pra usar soma acumulada:

SELECT
    column_name,
    SUM(column_name) OVER (PARTITION BY partition_column ORDER BY order_column) AS cumulative_sum
FROM 
    table_name;

O que rola aqui:

  • SUM(column_name) — soma os valores.
  • OVER() — define a janela pra calcular.
  • PARTITION BY — separa os dados em grupos (opcional).
  • ORDER BY — define a ordem das linhas dentro da janela.

Exemplo: receita acumulada por mês

Imagina uma tabela das suas receitas:

mês receita
2023-01 1000
2023-02 1500
2023-03 2000

A gente quer ver a receita de cada mês e o acumulado. Bora montar a query SQL:

SELECT
    mês,
    receita,
    SUM(receita) OVER (ORDER BY mês) AS receita_acumulada
FROM 
    receitas;

Resultado:

mês receita receita_acumulada
2023-01 1000 1000
2023-02 1500 2500
2023-03 2000 4500

O que tá rolando:

  1. ORDER BY mês dentro do OVER() diz pro PostgreSQL considerar as linhas em ordem cronológica.
  2. Pra cada linha, a soma é feita levando em conta todas as linhas anteriores (e a atual).

Pensa bem no que acontece aqui. Na primeira linha, SUM() soma só a primeira linha, na segunda — soma as duas primeiras, na terceira — soma as três. Por isso a ordem dos meses é super importante!

Exemplo: receita acumulada por região

Se você tivesse uma tabela de vendas por região, um pedaço dela seria assim:

região mês receita
Norte 2023-01 1000
Norte 2023-02 1500
Sul 2023-01 2000
Sul 2023-02 2500

Agora a gente quer calcular a receita acumulada separada pra cada região:

SELECT
    região,
    mês,
    receita,
    SUM(receita) OVER (PARTITION BY região ORDER BY mês) AS receita_acumulada
FROM 
    vendas;

O resultado vai ser assim:

região mês receita receita_acumulada
Norte 2023-01 1000 1000
Norte 2023-02 1500 2500
Sul 2023-01 2000 2000
Sul 2023-02 2500 4500

Agora cada região é analisada separadamente (PARTITION BY região), mas dentro da região as linhas ficam em ordem de tempo (ORDER BY mês).

Média móvel (AVG())

Beleza, somas acumuladas são massa, mas e se você quiser analisar tendências, tipo, dos últimos 3 meses? Pra isso serve a média móvel.

Exemplo: média móvel das receitas

De novo, vamos usar a tabela receitas, e os dados são:

mês receita
2023-01 1000
2023-02 1500
2023-03 2000
2023-04 2500

Query pra calcular a média móvel de 3 meses:

SELECT
    mês,
    receita,
    AVG(receita) OVER (
        ORDER BY mês 
        ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
    ) AS media_movel
FROM 
    receitas;

Resultado:

mês receita media_movel
2023-01 1000 1000
2023-02 1500 1250
2023-03 2000 1500
2023-04 2500 2000

Explicando:

  1. ROWS BETWEEN 2 PRECEDING AND CURRENT ROW diz pro PostgreSQL olhar pra linha atual e as duas anteriores pra calcular a média.
  2. No fim, pra cada mês a gente vê a média das receitas dos últimos 3 meses.

Ou seja, pra cada linha a gente define uma janela de 3 linhas: a atual e as duas anteriores. Depois calcula a média. Muito prático.

Como o ORDER BY afeta tudo

Funções de janela dependem da ordem certa das linhas. Se a ordem estiver errada (ou nem for definida), os resultados podem ficar bem estranhos.

Exemplo: erro por falta de ORDER BY

Se a gente tirar o ORDER BY do OVER(), em vez da soma acumulada, vamos pegar a soma total das receitas em cada linha:

SELECT
    mês,
    receita,
    SUM(receita) OVER () AS soma_acumulada_errada
FROM 
    receitas;

Resultado:

mês receita soma_acumulada_errada
2023-01 1000 7000
2023-02 1500 7000
2023-03 2000 7000
2023-04 2500 7000

As linhas não estão ordenadas, e em vez da soma acumulada, a função só soma tudo pra cada linha, sem critério.

Casos reais de uso

Análise de receitas:

  • Somas acumuladas ajudam a acompanhar como as vendas ou receitas da empresa crescem.
  • Média móvel mostra a tendência "limpa", sem ruídos.

Modelagem financeira:

Bancos e empresas financeiras usam funções de janela pra analisar pagamentos, crescimento de dívidas e outras métricas.

Análise de séries temporais:

Dados de tempo, tipo número de usuários online, visualizações de página, faturamento etc., são perfeitos pra analisar com SUM() e AVG().

2
Tarefa
SQL SELF, nível 29, lição 4
Bloqueado
Média móvel para os últimos 3 meses
Média móvel para os últimos 3 meses
1
Pesquisa/teste
Funções de janela, nível 29, lição 4
Indisponível
Funções de janela
Funções de janela
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION