Накопительное обновление для предыдущих записей - PullRequest
0 голосов
/ 16 мая 2018

У меня есть таблица, которая показывает эту информацию

Month   NewClients   OnHoldClients
5-2017  10           2
6-2017  16           4
7-2017  11           1
8-2017  15           6
9-2017  18           7

Я пытаюсь найти общую сумму за каждый месяц что

(Новые клиенты - OnHoldClients) + Всего за предыдущий месяц

как то так

Month   NewClients   OnHoldClients   Total
5-2017  10           2               8
6-2017  16           4               20
7-2017  11           1               30
8-2017  15           6               39
9-2017  18           7               50

запрос, который я пытался создать, был примерно таким, но я думаю, что это должен быть более простой способ сделать это

UPDATE MyTable
SET Total = (SELECT TOP 1 Total FROM MyTable B WHERE B.Month < A.Month) + NewClients - OnHoldClients
FROM MyTable A

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

Попробуйте это

;WITH CTE([Month],NewClients,OnHoldClients)
AS
(
SELECT '5-2017',10,2 UNION ALL
SELECT '6-2017',16,4 UNION ALL
SELECT '7-2017',11,1 UNION ALL
SELECT '8-2017',15,6 UNION ALL
SELECT '9-2017',18,7
)
SELECT [Month],
        NewClients,
        OnHoldClients,
        SUM(MonthTotal)OVER( ORDER BY [Month]) AS Total
FROM
(
SELECT [Month],
        NewClients,
        OnHoldClients,
        SUM(NewClients-OnHoldClients)OVER(PArtition by [Month] Order by [Month]) AS MonthTotal
FROM CTE
)dt

Результат, Демо: http://rextester.com/DKLG54359

Month   NewClients  OnHoldClients   Total
--------------------------------------------
5-2017      10          2            8
6-2017      16          4            20
7-2017      11          1            30
8-2017      15          6            39
9-2017      18          7            50
0 голосов
/ 16 мая 2018

Прежде чем мы начнем, обратите внимание на тот факт, что вы сталкиваетесь с такой вычислительной проблемой, это признак того, что, возможно, у вас не самый лучший дизайн.Обычно для этой цели рассчитанные значения сохраняются в процессе вставки записей.Так что я бы сказал, что вам лучше начать с общего поля и рассчитать его как накопление записей.

Теперь давайте перейдем к проблеме.я написал запрос, который делает это хорошо, но он немного многословен из-за рекурсивного характера проблемы.Тем не менее, он дает точный ожидаемый результат:

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 в список проекций.

...