DÍA 34Fechas y funciones de ventana · SQL para Análisis de Datos

Suma valores hasta cada periodo con un orden y un marco explícitos.

Día 34 20 minIntermedio

Calcular totales acumulados con una ventana

Objetivos

Al terminar podrás sumar desde el primer periodo observado hasta la fila actual sin reemplazar el total de cada periodo.

Concepto

SUM(valor) OVER (...) calcula una suma relacionada con las filas de la ventana y conserva cada fila mensual. El marco ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW define el acumulado desde la primera fila del orden hasta la actual.

Un acumulado depende del orden elegido. Aquí es cronológico y solo recorre los meses presentes en payment; no inventa meses sin actividad.

Ejemplo

WITH monthly AS (
  SELECT
    DATE_FORMAT(payment_date, '%Y-%m') AS payment_month,
    SUM(amount) AS total_amount
  FROM payment
  GROUP BY DATE_FORMAT(payment_date, '%Y-%m')
)
SELECT
  payment_month,
  ROUND(total_amount, 2) AS monthly_amount,
  ROUND(
    SUM(total_amount) OVER (
      ORDER BY payment_month
      ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ),
    2
  ) AS cumulative_amount
FROM monthly
ORDER BY payment_month;

monthly_amount describe una sola etiqueta temporal. cumulative_amount suma desde el primer mes observado hasta el actual.

Práctica guiada

  1. Cambia el orden a DESC y explica desde qué fila comienza el acumulado.
  2. Quita el marco ROWS y revisa cómo los empates pueden influir en el marco predeterminado.
  3. Añade el conteo de pagos mensual junto al importe acumulado.

Reto

Calcula un total acumulado por staff_primary_store_id ordenado por mes, usando un marco explícito. Antes de consultar, decide si necesitas un acumulado independiente por tienda.

Ver respuesta al reto
WITH monthly AS (
  SELECT s.store_id AS staff_primary_store_id,
         DATE_FORMAT(p.payment_date, '%Y-%m') AS payment_month,
         SUM(p.amount) AS monthly_total
  FROM sakila.payment AS p
  JOIN sakila.staff AS s ON s.staff_id = p.staff_id
  GROUP BY s.store_id, DATE_FORMAT(p.payment_date, '%Y-%m')
)
SELECT staff_primary_store_id, payment_month,
       ROUND(monthly_total, 2) AS monthly_total,
       ROUND(SUM(monthly_total) OVER (
         PARTITION BY staff_primary_store_id ORDER BY payment_month
         ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
       ), 2) AS running_total
FROM monthly
ORDER BY staff_primary_store_id, payment_month;

PARTITION BY inicia el acumulado por separado para cada tienda principal asignada al personal.

Quiz

1. ¿Qué define UNBOUNDED PRECEDING AND CURRENT ROW?
2. ¿Qué función asigna una posición única a cada fila?
3. ¿Qué aporta PARTITION BY a una función de ventana?

Comprobación

Ya analizas periodos y ventanas. En el proyecto final aplicarás filtros, uniones, métricas y verificaciones sobre Sakila.

TU PROGRESO

Cargando estado…