ProgramaciónDesarrollador Backend

¿Cómo implementar el cálculo de totales acumulativos en SQL sin funciones de ventana, considerando el rendimiento en miles o millones de filas?

Supere entrevistas con el asistente de IA Hintsage

Respuesta

El cálculo de totales acumulativos y sumas en curso se ha resuelto tradicionalmente en SQL a través de funciones de ventana (por ejemplo, SUM() OVER(ORDER BY ...)), sin embargo, en versiones anteriores o simplificadas de las bases de datos solo se dispone de subconsultas y agrupaciones. Históricamente, los arquitectos de bases de datos buscaban soluciones alternativas hasta la llegada del estándar SQL:2003 que soporta funciones de ventana.

Problema — En ausencia de funciones de ventana, es necesario calcular explícitamente la suma de todos los valores anteriores para cada fila, lo que resulta en consultas anidadas O(N^2) en conjuntos de datos grandes, a menos que se apliquen trucos.

Solución:

Normalmente se utilizan subconsultas correlacionadas o tablas temporales con actualización de valores:

Ejemplo de código:

-- Suma acumulativa con subconsulta correlacionada SELECT t1.id, t1.amount, ( SELECT SUM(t2.amount) FROM transactions t2 WHERE t2.id <= t1.id ) AS running_total FROM transactions t1 ORDER BY t1.id; -- A través de una tabla temporal con actualización manual de valores CREATE TEMPORARY TABLE temp_running (id INT, amount INT, running_total INT); -- Se recorre las filas mediante código externo (por ejemplo, pl/pgsql), añadiendo secuencialmente la suma

Características clave:

  • El método funciona solo si hay un criterio de orden único (id, fecha de creación)
  • Las subconsultas correlacionadas no escalan bien — crecimiento exponencial del tiempo de ejecución
  • Para grandes volúmenes de datos, es más lógico usar ETL con agregación fuera de SQL o mediante procedimientos

Preguntas trampa.

¿Garantiza la ordenación ORDER BY en una subconsulta correlacionada?

No — la subconsulta no necesariamente afecta el resultado mismo. La ordenación del conjunto final siempre se establece externamente en la consulta principal: el resultado depende solo de la filtración por WHERE.

¿Se puede paralelizar el cálculo de la suma acumulativa en este enfoque?

No — la secuencia es muy importante, especialmente al calcular en función de filas anteriores, por lo que la simple paralelización no es posible en SQL normal.

¿Por qué es tan lenta la subconsulta correlacionada con un gran número de filas?

Porque para cada fila se vuelve a calcular la suma sobre el conjunto de filas anteriores. Esto lleva a O(N^2) operaciones. Con un conjunto de 100 mil filas, esto ya puede tardar minutos o incluso horas.

Errores comunes y antipatrón

  • Filtración incorrecta por id en lugar de la fecha real — las sumas "saltan" debido a huecos en los ids
  • Intento de realizar la suma sin ordenar los datos
  • Uso de este enfoque para tablas enormes, donde se requiere ETL o procesamiento particionado

Ejemplo de la vida real

Caso negativo

Un analista calculó la recaudación acumulativa diaria por fecha a través de una subconsulta correlacionada, y de forma periódica, aparecían ids eliminados (huecos) en la tabla. La suma total tenía caídas abruptas y dependía no de la fecha, sino del orden de los ids.

Pros:

  • Funciona para conjuntos pequeños, no requiere funciones de ventana

Contras:

  • Los datos son incorrectos, calcula de manera diferente a lo esperado
  • Soporte complicado

Caso positivo

Un ingeniero llevó el procesamiento de la suma acumulativa a un script ETL (Python/pandas), y luego cargó los valores finales en una tabla separada, sincronizando solo las novedades. Los totales siempre están acordes a la fecha, el código funciona rápido y con millones de registros.

Pros:

  • Fiabilidad, capacidad de recalcular sin tiempo de inactividad
  • Capacidad de manejar grandes volúmenes

Contras:

  • Paisaje más complicado — se requieren herramientas de procesamiento externas