Sql server 以前记录的累积更新

Sql server 以前记录的累积更新,sql-server,sql-update,accumulate,Sql Server,Sql Update,Accumulate,我有一张表显示了这些信息 Month NewClients OnHoldClients 5-2017 10 2 6-2017 16 4 7-2017 11 1 8-2017 15 6 9-2017 18 7 我正在努力找出每个月的累计金额 那是 新客户-OnHoldClient+上个月总计 像这样的 Month NewClients OnHoldClients To

我有一张表显示了这些信息

Month   NewClients   OnHoldClients
5-2017  10           2
6-2017  16           4
7-2017  11           1
8-2017  15           6
9-2017  18           7
我正在努力找出每个月的累计金额 那是

新客户-OnHoldClient+上个月总计

像这样的

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

在我们开始之前,请注意一个事实,即你正面临这样的计算问题,这表明你可能没有最好的设计。为此,通常在插入记录的过程中存储计算值。所以我想说,你最好有一个总字段开始,并计算它作为记录积累

现在让我们着手解决手头的问题。我编写了一个查询,它很好地做到了这一点,但由于问题的递归性质,它有点冗长。然而,它产生了准确的预期结果:

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结构,从每个记录一直到最初的一个月,加起来就是最终的总值。此查询仅包括月份和总计字段,但您可以轻松地将其他两个字段添加到投影列表中。

在开始之前,请注意,您面临的计算问题只是一个症状,即您可能没有最好的设计。为此,通常在插入记录的过程中存储计算值。所以我想说,你最好有一个总字段开始,并计算它作为记录积累

现在让我们着手解决手头的问题。我编写了一个查询,它很好地做到了这一点,但由于问题的递归性质,它有点冗长。然而,它产生了准确的预期结果:

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结构,从每个记录一直到最初的一个月,加起来就是最终的总值。此查询仅包括月份和总计字段,但您可以轻松地将其他两个字段添加到投影列表中。

尝试此操作

;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
结果,演示:

试试这个

;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
结果,演示: