
Imagine que você tenha o faturamento mensal de uma empresa:
| Mês | Faturamento |
|---|---|
| Julho | R$ 180.000 |
| Agosto | R$ 210.000 |
| Setembro | R$ 195.000 |
| Outubro | R$ 230.000 |
Olhar para esses números já nos mostra alguma coisa.
Mas normalmente a pergunta seguinte é:
Quanto cada mês cresceu ou caiu em relação ao mês anterior?
Agora precisamos comparar linhas.
Agosto precisa olhar para julho.
Setembro precisa olhar para agosto.
Outubro precisa olhar para setembro.
É justamente esse tipo de problema que ajuda a entender o LAG().
Primeiro precisamos calcular o faturamento mensal
Imagine nossa tabela pedido:
pedido
----------------
ID_PEDIDO
ID_CLIENTE
DATA_PEDIDO
VALOR_TOTALPodemos calcular o faturamento por mês:
SELECT
YEAR(DATA_PEDIDO) AS ANO,
MONTH(DATA_PEDIDO) AS MES,
SUM(VALOR_TOTAL) AS FATURAMENTO
FROM pedido
GROUP BY
YEAR(DATA_PEDIDO),
MONTH(DATA_PEDIDO);O resultado poderia ser:
| ANO | MES | FATURAMENTO |
|---|---|---|
| 2026 | 7 | 180000 |
| 2026 | 8 | 210000 |
| 2026 | 9 | 195000 |
| 2026 | 10 | 230000 |
Até aqui utilizamos uma agregação normal.
Uma linha representa um mês.
Agora surge o problema:
Como colocar o faturamento do mês anterior ao lado do faturamento atual?
É aqui que entra o LAG()
Podemos primeiro calcular o faturamento mensal e depois utilizar LAG():
WITH venda_mensal AS (
SELECT
YEAR(DATA_PEDIDO) AS ANO,
MONTH(DATA_PEDIDO) AS MES,
SUM(VALOR_TOTAL) AS FATURAMENTO
FROM pedido
GROUP BY
YEAR(DATA_PEDIDO),
MONTH(DATA_PEDIDO)
)
SELECT
ANO,
MES,
FATURAMENTO,
LAG(FATURAMENTO) OVER (
ORDER BY ANO, MES
) AS FATURAMENTO_ANTERIOR
FROM venda_mensal;Agora o resultado fica parecido com:
| ANO | MES | FATURAMENTO | FATURAMENTO_ANTERIOR |
|---|---|---|---|
| 2026 | 7 | 180000 | NULL |
| 2026 | 8 | 210000 | 180000 |
| 2026 | 9 | 195000 | 210000 |
| 2026 | 10 | 230000 | 195000 |
Observe o que LAG() fez.
Para agosto, trouxe julho… para setembro, trouxe agosto… para outubro, trouxe setembro.
Em outras palavras:
LAG permite acessar um valor de uma linha anterior sem perder a linha atual.
Por que precisamos do ORDER BY?
Esta parte é fundamental:
LAG(FATURAMENTO) OVER (
ORDER BY ANO, MES
)Para saber qual é a linha anterior, o SQL precisa saber qual é a ordem.
Neste caso:
Julho
↓
Agosto
↓
Setembro
↓
OutubroSem uma ordem definida, a expressão “mês anterior” não faria sentido.
💡 Quando utilizar LAG(), uma das primeiras perguntas deve ser:
Anterior em qual ordem?
Agora podemos calcular a diferença
Depois de trazer o faturamento anterior, conseguimos comparar os dois valores.
WITH venda_mensal AS (
SELECT
YEAR(DATA_PEDIDO) AS ANO,
MONTH(DATA_PEDIDO) AS MES,
SUM(VALOR_TOTAL) AS FATURAMENTO
FROM pedido
GROUP BY
YEAR(DATA_PEDIDO),
MONTH(DATA_PEDIDO)
),
venda_comparada AS (
SELECT
ANO,
MES,
FATURAMENTO,
LAG(FATURAMENTO) OVER (
ORDER BY ANO, MES
) AS FATURAMENTO_ANTERIOR
FROM venda_mensal
)
SELECT
ANO,
MES,
FATURAMENTO,
FATURAMENTO_ANTERIOR,
FATURAMENTO - FATURAMENTO_ANTERIOR AS DIFERENCA
FROM venda_comparada;Teríamos:
| Mês | Atual | Anterior | Diferença |
|---|---|---|---|
| Julho | 180.000 | NULL | NULL |
| Agosto | 210.000 | 180.000 | +30.000 |
| Setembro | 195.000 | 210.000 | -15.000 |
| Outubro | 230.000 | 195.000 | +35.000 |
Agora nossa consulta não mostra apenas quanto vendemos.
Ela mostra como o resultado mudou.
E por que julho aparece como NULL?
Porque julho é a primeira linha do nosso resultado.
Dentro dos dados analisados, não existe uma linha anterior.
Então:
LAG(FATURAMENTO)não possui nenhum valor para buscar.
O NULL não é um erro.
Ele está dizendo:
Não existe um período anterior disponível nesta consulta para fazer a comparação.
Cuidado com um detalhe importante
Imagine que nossa base tenha:
Julho
Agosto
OutubroSetembro não aparece porque não houve registros.
Ao utilizar LAG(), outubro vai olhar para a linha anterior:
Agosto.
Mas agosto não é o mês imediatamente anterior a outubro.
Isso nos mostra algo importante:
LAG()busca a linha anterior de acordo com a ordenação. Ele não entende sozinho o significado de “mês anterior”.
Se sua análise exige todos os meses do calendário, inclusive aqueles sem vendas, você precisa garantir que esses períodos existam no conjunto analisado.
⚠️ Esse detalhe evita muitas interpretações erradas.
O LAG não serve apenas para vendas
Agora que entendemos o raciocínio, podemos trocar o problema.
Podemos comparar:
faturamento deste mês com o anterior;
quantidade vendida hoje com ontem;
preço atual com o preço anterior;
saldo atual com o saldo anterior;
desempenho atual de um produto com o período anterior.
A lógica continua parecida:
valor atual
↓
buscar valor anterior
↓
comparar
↓
medir a mudançaÉ isso que vale aprender.
Um desafio para você
Já temos:
FATURAMENTO
FATURAMENTO_ANTERIORE calculamos:
FATURAMENTO - FATURAMENTO_ANTERIORAgora imagine que a empresa pergunte:
Qual foi a variação percentual em relação ao mês anterior?
Por exemplo:
Agosto
Atual: 210.000
Anterior: 180.000
Crescimento: ?Tente montar o cálculo antes de procurar uma solução pronta.
Você já possui os dois valores necessários.
O restante é raciocínio.
Conclusão
LAG() começa a fazer sentido quando deixamos de olhar cada linha isoladamente.
Nossa pergunta era:
Como o faturamento atual se compara ao período anterior?
Então precisamos:
- calcular o resultado de cada período;
- definir a ordem desses períodos;
- trazer o valor da linha anterior;
- comparar os dois valores.
Só depois aparece:
LAG(FATURAMENTO) OVER (
ORDER BY ANO, MES
)Não é apenas mais uma Window Function para decorar.
É uma ferramenta para responder uma pergunta muito comum em análise:
O que mudou em relação ao que veio antes?
Próximo passo
Na Coleção A Arte da Query, você pratica SQL a partir de cenários em que existe uma pergunta para investigar antes de existir uma função para utilizar.
Porque no trabalho ninguém vai chegar dizendo:
“Preciso que você use
LAG().”
A pergunta será:
“Nossas vendas cresceram ou caíram em relação ao período anterior?”
E seu trabalho será transformar essa pergunta em uma análise.
Aqui fiz questão de incluir um único cuidado técnico realmente importante: LAG() significa linha anterior, não necessariamente mês anterior. Isso mantém o artigo curto, mas evita que o leitor saia com uma compreensão tecnicamente incompleta.
0 Comentários