【问题标题】:Cumulative Total in MS Sql server [duplicate]MS Sql 服务器中的累积总计 [重复]
【发布时间】:2012-07-24 17:38:52
【问题描述】:

可能重复:
Calculate a Running Total in SqlServer

我需要在 ms-sql 服务器中获取列的累积(运行)总数。 IE。如果有一个名为“Marks”的列,则对应每一行的累积总和将是当前行和之前行的总和。我们可以在不使用连接的情况下获得结果吗?因为我的查询很大。

我已经包含了一个示例表和数据:

CREATE TABLE "SCORE_CHART" 
   (    
        "STUDENT_NAME" NVARCHAR(20), 
        "MARKS" INT
   )

INSERT INTO SCORE_CHART (STUDENT_NAME, MARKS) VALUES ('STUD1', 95);
INSERT INTO SCORE_CHART (STUDENT_NAME, MARKS) VALUES ('STUD2', 90);
INSERT INTO SCORE_CHART (STUDENT_NAME, MARKS) VALUES ('STUD3', 98);

SELECT STUDENT_NAME, MARKS FROM SCORE_CHART;

预期结果:

在 oracle 中很容易写成这样:

SELECT 
  STUDENT_NAME,
  MARKS,
  SUM(MARKS) OVER (ORDER BY STUDENT_NAME) CUM_SUM
FROM SCORE_CHART
ORDER BY STUDENT_NAME;

提前致谢。

【问题讨论】:

  • 我看不到您的预期结果(imgur 在工作中被阻止) - 您可以发布一个基于文本的示例吗?
  • 第一行累计总和应该是95,第二行是185,第三行是283。

标签: sql sql-server sql-server-2008 tsql sql-server-2005


【解决方案1】:

只是做一个连接似乎并不能保证顺序,但得出的最终答案是好的:

select 
  x.STUDENT_NAME
  , sum(y.marks) marks
from 
    SCORE_CHART x
       join SCORE_CHART y
          on x.STUDENT_NAME <= y.STUDENT_NAME
group by x.STUDENT_NAME
order by x.STUDENT_NAME

只是看起来 NO JOINS 规则 - 会重新考虑

编辑 - 现在运行正常:LIVE FIDDLE HERE

创建数据

CREATE TABLE "SCORE_CHART"     
(             
  "STUDENT_NAME" NVARCHAR(20),          
  "MARKS" INT    
)  
INSERT INTO SCORE_CHART (STUDENT_NAME, MARKS) 
VALUES 
('STUD1', 95),
('STUD2', 90),
('STUD3', 98)

使用递归 CTE:

 ;WITH 
    init_cte(row,STUDENT_NAME,MARKS) 
    AS
        (
        SELECT 
        ROW_NUMBER() OVER (ORDER BY STUDENT_NAME),
        STUDENT_NAME,
        MARKS
        FROM SCORE_CHART
        )
    ,MinMax_cte(MinRow,MaxRow)  AS (SELECT MIN(row),MAX(row) FROM init_cte)

    ,recursive_cte (row,STUDENT_NAME,MARKS,RUNNING_MARKS) AS 
      (
         SELECT row,STUDENT_NAME,MARKS,MARKS 
            FROM init_cte 
            WHERE row = (SELECT MinRow FROM  MinMax_cte) 
         UNION ALL
         SELECT Y.row,y.STUDENT_NAME,y.MARKS,x.RUNNING_MARKS + y.MARKS
            FROM recursive_cte x
            INNER JOIN init_cte y
                ON y.row = x.row + 1
            WHERE y.row <= (SELECT [MaxRow] from MinMax_cte)
      )
SELECT * FROM recursive_cte

正如在给您的评论中提到的 OP 有一个类似的问题 HERE ON SO 在那个问题中,Sam Saffron 提出了一种非常优雅的方法来使用UPDATE 进行总计。这适用于您的数据:

使用上面创建的相同数据,但使用 UPDATE 技巧:

CREATE TABLE #t ( ROW int, STUDENT_NAME NVARCHAR(20) , MARKS int, MARKS_RUNNING int) 
INSERT INTO #t
SELECT
        ROW_NUMBER() OVER (ORDER BY STUDENT_NAME),
        STUDENT_NAME, 
        MARKS,
        0
FROM SCORE_CHART

DECLARE @total int  
SET @total = 0 
UPDATE #t SET marksrunning = @total, @total = @total + MARKS   

SELECT * FROM #t 

【讨论】:

    【解决方案2】:

    检查递归 CTE 的查询。

    ;with CTE as (select ROW_NUMBER() over (order by (select 0)) as id,STUDENT_NAME,MARKS from SCORE_CHART)
    ,CTE1 as (
    
    select id,STUDENT_NAME,marks,marks as CUM_SUM from CTE where id=1
    UNION ALL
    select c.id,c.STUDENT_NAME,c.marks,c.marks+c1.CUM_SUM as CUM_SUM from CTE1 c1 inner join CTE c on c.id-1=c1.id)
    select * from CTE1
    

    【讨论】:

    • @techdo +1 是通常的回应
    【解决方案3】:

    你说不加入,那么申请呢? ;)

    SELECT STUDENT_NAME, MARKS, running.total
    FROM SCORE_CHART a
    cross apply 
    (
        select SUM(marks) total 
        from score_chart b
        where b.student_name <= a.student_name
    ) running
    ORDER BY STUDENT_NAME;
    

    加上student_name的索引速度应该没问题!

    【讨论】:

    • 感谢您的回复,查询对于给定的数据工作正常。问题是我的选择包含 3-4 个表连接,所以要实现 CROSS APPLY,我必须将所有内容放在内部查询中,而且看起来很大。再次感谢您的帮助。
    【解决方案4】:

    试试这个:

    你可以通过加入同一张表本身来获得累计和

    SELECT S1.STUDENT_NAME, S1.MARKS ,sum(S2.MARKS) CUM_SUM
    FROM SCORE_CHART S1 join SCORE_CHART S2
    on S1.STUDENT_NAME>=S2.STUDENT_NAME
    group by S1.STUDENT_NAME, S1.MARKS 
    order by S1.STUDENT_NAME, S1.MARKS
    

    SQL Fiddle demo

    【讨论】:

    • 这会很慢。请参考我发布的链接
    【解决方案5】:

    使用递归 CTE 来实现这一点。

    【讨论】:

    • 你能发布这个表结构的查询吗?
    • 我在我的答案中添加了一个递归 CTE 完整示例......这不是最容易理解的结构,(但每次我写一个时疼痛都会减轻一点!)
    • 用递归CTE检查sql查询。刚刚我已经上传了。
    【解决方案6】:

    从 2012 年起支持相同的查询。在旧版本中,有几种方法。参考这个http://www.sqlperformance.com/2012/07/t-sql-queries/running-totals

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-04
      • 2017-03-23
      • 2020-10-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多