¿Cómo comparo cada fila con la del mes anterior en SQL con LAG?
Trae las ventas del mes anterior a cada fila con LAG y calcula cuánto subieron o bajaron.
Curso gratis. Tu Maestro, una IA, .
"¿Cuánto vendimos más que el mes pasado?" Para restar, necesitas las ventas del mes anterior en la misma fila que las del mes actual. LAG hace exactamente eso: trae un valor de la fila anterior de su partición.
LAG(ventas)traeventasde la fila anterior.LEAD(ventas)traeventasde la fila siguiente.OVER (PARTITION BY sucursal ORDER BY mes)dice qué es "anterior": la fila previa de la misma sucursal, ordenada por mes; solo coincide con el mes calendario anterior si no hay huecos.
Si no le dices más, LAG mira una fila atrás y, cuando no hay fila anterior, regresa NULL.
ventas - LAG(ventas) OVER ( PARTITION BY sucursal ORDER BY mes) AS cambioInténtalo
Antes de escribir la consulta, contesta la pregunta de abajo. Luego corre tu consulta y revisa tu respuesta en la fila de enero. Si los números de una sucursal se mezclan con los de otra, pregúntale a tu Maestro.
Comprueba lo que sabes: Antes de correr: ¿qué sale en la columna cambio en la fila de enero de Centro?
Tu turno
Regresa sucursal, mes, ventas, ventas_anterior (las ventas de la fila anterior de la misma sucursal, con LAG) y cambio (ventas menos ventas_anterior). Ordena por sucursal, mes. Terminaste cuando ves 35 filas y febrero de Centro dice 165100 y -9400.
Tablas: ventas_mensuales (sucursal, mes, ventas)
ventas_mensuales · 35 filas
| Columna | Tipo |
|---|---|
| sucursal Nombre de la sucursal: Centro, Norte o Sur. | VARCHAR |
| mes Primer día del mes que resume la fila. | DATE |
| ventas Ventas del mes, en pesos. | BIGINT |
Primeras filas
| sucursal | mes | ventas |
|---|---|---|
| Centro | 2025-01-01 | 165100 |
| Centro | 2025-02-01 | 155700 |
| Centro | 2025-03-01 | 178700 |
Tab agrega sangría; Esc y Tab para salir
Fila por fila
Así quedaron los primeros meses de Centro al correr la solución en el sandbox de Maestro. Lee la tabla en diagonal: el ventas de una fila baja a la columna ventas_anterior de la fila siguiente.
| mes | ventas | ventas_anterior | cambio |
|---|---|---|---|
| 2025-01-01 | 165100 | NULL | NULL |
| 2025-02-01 | 155700 | 165100 | -9400 |
| 2025-03-01 | 178700 | 155700 | 23000 |
| 2025-04-01 | 175800 | 178700 | -2900 |
LAG no busca "el mes pasado" en el calendario. Hace algo más simple: dentro de la partición de Centro, ordenada por mes, toma la fila que está justo arriba. Cuando la consulta pasa a la primera fila de Norte, no hay fila arriba dentro de Norte, y por eso enero de Norte también recibe NULL.
La gráfica dibuja la columna cambio de Centro. Vega-Lite tiene su propia ventana con lag, y la gráfica la usa para calcular cada barra a partir de las ventas.
En enero sale NULL en las dos columnas nuevas: es la primera fila de su sucursal, así que no hay fila anterior. Y cualquier resta con NULL da NULL. Eso es correcto: no sabes cuánto cambió enero porque la tabla no tiene diciembre de 2024.
PARTITION BY sucursal evita mezclar sucursales. Sin él, con ORDER BY mes, una fila puede tomar otra sucursal del mismo mes como anterior; entre meses empatados tampoco hay un orden único. El ORDER BY sucursal, mes final solo ordena lo que ves, no cambia el orden de la ventana.
Lo que cambia el número
El 0 que parece inocente. LAG acepta un tercer argumento: el valor que regresa cuando no hay fila anterior. Es tentador escribir LAG(ventas, 1, 0) para no ver NULL. En el sandbox, con esa versión, enero de Centro reportó un cambio de 165100: parece que la sucursal creció todo lo que vendió. Un NULL dice "no sé"; un 0 inventado dice algo falso. Deja el NULL, o explícalo en el reporte.
El porcentaje. Casi nunca te piden la resta, te piden "cuánto creció en porcentaje": el cambio entre las ventas anteriores. En la corrida, febrero de Centro dio -5.7 y marzo 14.8. Cuando la misma ventana aparece tres veces, la cláusula WINDOW le pone nombre una sola vez, y DuckDB la aceptó tal cual (abajo). Si el valor anterior puede ser 0, protege la división con NULLIF(LAG(ventas) OVER w, 0).
Un empate en el orden. Si dos filas de la partición comparten el valor del ORDER BY, cuál es "la anterior" no está garantizado, igual que con ROW_NUMBER. Desempata con una columna que no se repita.
Hacia adelante. LEAD funciona igual en la otra dirección: en la corrida, LEAD(ventas) en enero de Centro trajo 155700, el de febrero, y en diciembre dio NULL porque no hay mes siguiente.
SELECT sucursal, mes, ventas, ventas - LAG(ventas) OVER w AS cambio, ROUND(100.0 * (ventas - LAG(ventas) OVER w) / LAG(ventas) OVER w, 1) AS pct_cambioFROM ventas_mensualesInicio de la línea 6. WINDOW w AS (PARTITION BY sucursal ORDER BY mes) Fin de la línea 6.ORDER BY sucursal, mes;Si te toca en una entrevista, puede sonar a "calcula el crecimiento mes contra mes de cada producto", "¿cuántos días pasaron entre cada compra de un usuario y la anterior?" o "encuentra a los usuarios que compraron dos días seguidos". Las tres son LAG con la partición correcta. La de los días es la misma idea con fechas: restas la fecha de la fila anterior. En la tabla pedidos, Elena tiene dos pedidos el 6 de febrero, así que el segundo dio 0 días, y su pedido 1028 llegó 15 días después del anterior. Si quieres practicar una de estas en voz alta, pídele a tu Maestro que te la pregunte.
En tus reportes: busca uno que compare "contra el periodo anterior" y revisa cómo lo calcula. Si hoy alguien copia la columna del mes pasado a mano o hace una unión de la tabla consigo misma, LAG lo resuelve en una línea. Y antes de entregarlo, lee la página siguiente: un mes que falta cambia lo que significa "anterior".
SELECT cliente, pedido_id, fecha,Inicio de las líneas 2–5. fecha - LAG(fecha) OVER ( PARTITION BY cliente ORDER BY fecha, pedido_id ) AS dias_desde_el_anterior Fin de las líneas 2–5.FROM pedidosORDER BY cliente, fecha, pedido_id;Comprueba lo que sabes: Un compañero escribió LAG(ventas, 1, 0) para que no salieran NULL. ¿Qué cambio reporta su consulta para enero de Centro?