【问题标题】:TSQL cumulative column from previous row [duplicate]上一行的 SQL 累积列 [重复]
【发布时间】:2012-09-14 14:52:36
【问题描述】:

可能重复:
Calculate a Running Total in SqlServer

我需要使用前一行的值来生成如下所示的累积值。对于 2000 年的每个代码,起始基数始终为 100。 我需要使用 tsql 代码来实现这一点。

id                Code              Yr             Rate           Base        

1                   4               2000           5              100                                  
2                   4               2001           7              107 (100+7)             
3                   4               2002           4              111 (107+4)                              
4                   4               2003           8              119 (111+8)
5                   4               2004           10             129 (119+10)
6                   5               2000           2              100
7                   5               2001           3              103 (100+3)
8                   5               2002           8              111 (103+8)
9                   5               2003           5              116 (111+5)
10                  5               2004           4              120 (116+4) 

【问题讨论】:

标签: tsql sql-server-2008-r2 cumulative-sum


【解决方案1】:

好的。我们有这样的桌子 CREATE Table MyTbl(id INT PRIMARY KEY IDENTITY(1,1), Code INT, Yr INT, Rate INT) 我们想通过代码计算累积值。 所以我们可以像这样使用查询:

1) 递归(需要更多资源,但输出结果如示例)

with cte as
(SELECT *, ROW_NUMBER()OVER(PARTITION BY Code ORDER BY Yr ASC) rn
FROM MyTbl),

recursion as
(SELECT id,Code,Yr,Rate,rn, CAST(NULL as int) as Tmp_base, CAST('100' as varchar(25)) AS Base FROM cte
WHERE rn=1
UNION ALL
SELECT cte.id,cte.Code,cte.Yr,cte.Rate,cte.rn, 
CAST(recursion.Base as int),
CAST(recursion.Base+cte.Rate as varchar(25))
FROM recursion JOIN cte ON recursion.Code=cte.Code AND recursion.rn+1=cte.rn
)

SELECT id,Code,Yr,Rate, 
CAST(Base as varchar(10))+ISNULL(' ('+ CAST(Tmp_base as varchar(10))+'+'+CAST(Rate as varchar(10))+')','') AS Base 
FROM recursion
ORDER BY 1


OPTION(MAXRECURSION 0)

2) 或者我们可以使用更快的查询而不使用递归。但是结果是不可能生成像'107(100+7)'这样的字符串(只有像'107'这样的字符串)

SELECT *,

    100 +
    (SELECT ISNULL(SUM(rate),0) /*we need to calculate only the sum in subquery*/
    FROM MyTbl AS a
    WHERE
        a.Code=b.Code /*the year in subquery equals the year in main query*/
        AND a.Yr<b.Yr /*main feature in our subquery*/
        ) AS base

FROM MyTbl AS b

【讨论】:

  • 每个特定代码的第一年的比率必须为 100。此外,后续的 Base 值必须是之前的 Base 值加上相应的当前 Rate。
  • 感谢这两个查询工作。如何更新数据库中的字段Base?
  • 第一次查询只需替换 SELECT id,Code,Yr,Rate, CAST(Base as varchar(10))+ISNULL(' ('+ CAST(Tmp_base as varchar(10))+'+ '+CAST(Rate as varchar(10))+')','') AS Base FROM recursion ORDER BY 1 OPTION(MAXRECURSION 0) to UPDATE MyTbl SET Base = (SELECT CAST(Base as varchar(10))+ISNULL (' ('+ CAST(Tmp_base as varchar(10))+'+'+CAST(Rate as varchar(10))+')','') AS NewBase FROM recursion WHERE MyTbl.id=recursion.id ) 选项(MAXRECURSION 0)
  • 第二个查询(完整): UPDATE MyTbl SET Base = ( SELECT 100 + (SELECT ISNULL(SUM(rate),0) FROM MyTbl AS a WHERE a.Code=b.Code AND a.Yr
  • 再次非常感谢迪玛。尽管第二个查询的一个观察结果是添加上一个 Rate 而不是使用下一个 Rate 来获取 Base。第一个查询完成了这项工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多