Прежде чем мы начнем, обратите внимание на тот факт, что вы сталкиваетесь с такой вычислительной проблемой, это признак того, что, возможно, у вас не самый лучший дизайн.Обычно для этой цели рассчитанные значения сохраняются в процессе вставки записей.Так что я бы сказал, что вам лучше начать с общего поля и рассчитать его как накопление записей.
Теперь давайте перейдем к проблеме.я написал запрос, который делает это хорошо, но он немного многословен из-за рекурсивного характера проблемы.Тем не менее, он дает точный ожидаемый результат:
DECLARE @dmin AS date = (SELECT min(mt.[Month]) from dbo.MyTable mt);
;WITH cte(_Month, _Total) AS (
SELECT mt.[Month] AS _Month, (mt.NewClients - mt.OnHoldClients) AS _Total
FROM dbo.MyTable mt
WHERE mt.[Month] = @dmin
UNION ALL
SELECT mt.[Month] AS _Month, ((mt.NewClients - mt.OnHoldClients) + ccc._Total) AS _Total
FROM dbo.MyTable mt
CROSS APPLY (SELECT cc._Total FROM (SELECT c._Total,
CAST((row_number() OVER (ORDER BY c._Month DESC)) AS int) as _Rank
FROM cte c WHERE c._Month < mt.[Month]) as cc
WHERE cc._Rank = 1) AS ccc
WHERE mt.[Month] > @dmin
)
SELECT c._Month, max(c._Total) AS Total
FROM cte c
GROUP BY c._Month
Это рекурсивная структура CTE, которая идет по каждой записи на протяжении всего пути к начальному месяцу и суммирует до итогового итогового значения.Этот запрос включает только поля «Месяц» и «Всего», но вы можете легко добавить остальные 2 в список проекций.