Calcular venta diaria y total acumulado
Situación
Necesitamos una serie diaria de ventas y, junto a cada día, el importe acumulado desde el inicio del periodo. La primera cifra reduce partidas a una fila diaria; la segunda utiliza esas filas sin volver a reducirlas.
Primera aproximación
Intentar aplicar directamente una función de ventana sobre las partidas vuelve difícil distinguir el total del día del acumulado. Primero construiremos el nivel diario y después calcularemos la ventana.
Una función de ventana calcula un valor sobre filas relacionadas sin reunirlas en una sola. En SUM(...) OVER (...), OVER define esas filas; el marco ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW comienza en la primera fila ordenada y termina en la fila que se está leyendo.
Antes de formar la serie diaria, CONVERT(DATE, pe.FechaPedido) conserva la fecha y retira la parte de hora para que todos los pedidos del mismo día pertenezcan al mismo grupo.
Consulta final
DECLARE @Desde DATE = '20260301';
DECLARE @Hasta DATE = '20260401';
WITH VentasDiarias AS
(
SELECT
CONVERT(DATE, pe.FechaPedido) AS Fecha,
SUM
(
d.Cantidad * d.PrecioUnitario
* (1 - d.Descuento / 100.0)
) AS VentaDia
FROM dbo.Pedido AS pe
INNER JOIN dbo.PedidoDetalle AS d
ON d.IdPedido = pe.IdPedido
WHERE pe.Estado IN ('Confirmado', 'Enviado')
AND pe.FechaPedido >= @Desde
AND pe.FechaPedido < @Hasta
GROUP BY CONVERT(DATE, pe.FechaPedido)
)
SELECT
v.Fecha,
v.VentaDia,
SUM(v.VentaDia) OVER
(
ORDER BY v.Fecha
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS VentaAcumulada
FROM VentasDiarias AS v
ORDER BY v.Fecha;
Recorrido
La CTE, una consulta con nombre disponible para la instrucción que sigue, filtra el periodo con un límite superior exclusivo y agrupa por fecha sin hora. VentaDia representa una fila por cada día que tuvo pedidos aceptados.
La segunda suma utiliza OVER: conserva esas filas y acumula desde la primera hasta la actual. Escribir explícitamente el marco ROWS deja claro qué filas participan y evita depender de comportamientos implícitos ante empates.
Resultado esperado
| Fecha | VentaDia | VentaAcumulada |
|---|---|---|
| 2026-03-01 | 728.00 | 728.00 |
| 2026-03-04 | 719.10 | 1447.10 |
| 2026-03-05 | 624.15 | 2071.25 |
Los días sin ventas no aparecen porque no existe una fila que agrupar.
Comprobación en SSMS
La cuadrícula permite seguir cómo cada venta diaria se incorpora al acumulado de la fila siguiente.

Variación: mostrar días en cero
Para una gráfica continua necesitamos una tabla calendario —una tabla con una fila por fecha y sus atributos—, o una secuencia de fechas controlada, y un LEFT JOIN contra VentasDiarias. Después convertimos la ausencia en cero mediante COALESCE.
También podemos agregar PARTITION BY para reiniciar el acumulado por mes, sucursal o moneda.
Límite o precaución
El acumulado solo es coherente si el orden es estable y las cifras comparten unidad. No sumamos monedas distintas ni mezclamos pedidos cancelados con ventas aceptadas.
Convertir la columna de fecha dentro del filtro puede dificultar el uso eficiente de un índice, una estructura que organiza valores para facilitar el acceso a filas. Por eso el WHERE compara la columna original con límites y reserva la conversión para agrupación y presentación.