如何获得累计金额

时间:2010-01-22 21:12:14

标签: sql-server sql-server-2008

declare  @t table
    (
        id int,
        SomeNumt int
    )

insert into @t
select 1,10
union
select 2,12
union
select 3,3
union
select 4,15
union
select 5,23


select * from @t

以上选择将返回以下内容。

id  SomeNumt
1   10
2   12
3   3
4   15
5   23

我如何获得以下

id  srome   CumSrome
1   10  10
2   12  22
3   3   25
4   15  40
5   23  63

16 个答案:

答案 0 :(得分:189)

select t1.id, t1.SomeNumt, SUM(t2.SomeNumt) as sum
from @t t1
inner join @t t2 on t1.id >= t2.id
group by t1.id, t1.SomeNumt
order by t1.id

SQL Fiddle example

<强>输出

| ID | SOMENUMT | SUM |
-----------------------
|  1 |       10 |  10 |
|  2 |       12 |  22 |
|  3 |        3 |  25 |
|  4 |       15 |  40 |
|  5 |       23 |  63 |

编辑:这是一种适用于大多数数据库平台的通用解决方案。如果您的特定平台有更好的解决方案(例如,gareth's),请使用它!

答案 1 :(得分:161)

最新版本的SQL Server(2012)允许以下内容。

SELECT 
    RowID, 
    Col1,
    SUM(Col1) OVER(ORDER BY RowId ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Col2
FROM tablehh
ORDER BY RowId

SELECT 
    GroupID, 
    RowID, 
    Col1,
    SUM(Col1) OVER(PARTITION BY GroupID ORDER BY RowId ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Col2
FROM tablehh
ORDER BY RowId

这更快。分区版本在34秒内完成超过500万行。

感谢Peso,他对另一个答案中提到的SQL Team线程发表了评论。

答案 2 :(得分:21)

对于SQL Server 2012以上,它可能很简单:

TypeError: Cannot read property 'status' of undefined

因为SELECT id, SomeNumt, sum(SomeNumt) OVER (ORDER BY id) as CumSrome FROM @t 的{​​{1}}条款默认表示ORDER BY用于窗口框架(&#34;一般说明&#34;在https://msdn.microsoft.com/en-us/library/ms189461.aspx

答案 3 :(得分:11)

CTE版本,只是为了好玩:

;
WITH  abcd
        AS ( SELECT id
                   ,SomeNumt
                   ,SomeNumt AS MySum
             FROM   @t
             WHERE  id = 1
             UNION ALL
             SELECT t.id
                   ,t.SomeNumt
                   ,t.SomeNumt + a.MySum AS MySum
             FROM   @t AS t
                    JOIN abcd AS a ON a.id = t.id - 1
           )
  SELECT  *  FROM    abcd
OPTION  ( MAXRECURSION 1000 ) -- limit recursion here, or 0 for no limit.

返回:

id          SomeNumt    MySum
----------- ----------- -----------
1           10          10
2           12          22
3           3           25
4           15          40
5           23          63

答案 4 :(得分:11)

让我们首先创建一个包含虚拟数据的表 - &gt;

Create Table CUMULATIVESUM (id tinyint , SomeValue tinyint)

**Now let put some data in the table**

Insert Into CUMULATIVESUM

Select 1, 10 union 
Select 2, 2  union
Select 3, 6  union
Select 4, 10 

在这里我加入了同桌(SELF Joining)

Select c1.ID, c1.SomeValue, c2.SomeValue
From CumulativeSum c1,  CumulativeSum c2
Where c1.id >= c2.ID
Order By c1.id Asc

结果:

ID  SomeValue   SomeValue
1   10          10
2   2           10
2   2            2
3   6           10
3   6            2
3   6            6
4   10          10
4   10           2
4   10           6
4   10          10

这里我们现在就把t2的Somevalue加起来,我们就得到了

Select c1.ID, c1.SomeValue, Sum(c2.SomeValue) CumulativeSumValue
From CumulativeSum c1,  CumulativeSum c2
Where c1.id >= c2.ID
Group By c1.ID, c1.SomeValue
Order By c1.id Asc
  

FOR SQL SERVER 2012及更高版本(更好的表现)

Select c1.ID, c1.SomeValue, 
SUM (SomeValue) OVER (ORDER BY c1.ID )
From CumulativeSum c1
Order By c1.id Asc

期望的结果

ID  SomeValue   CumlativeSumValue
1   10          10
2   2           12
3   6           18
4   10          28

Drop Table CumulativeSum

清除虚拟表格

答案 5 :(得分:5)

迟到的答案,但又显示了一种可能性......

使用CROSS APPLY逻辑可以更优化累积和生成。

效果优于INNER JOIN&amp;分析实际查询计划时OVER Clause ...

/* Create table & populate data */
IF OBJECT_ID('tempdb..#TMP') IS NOT NULL
DROP TABLE #TMP 

SELECT * INTO #TMP 
FROM (
SELECT 1 AS id
UNION 
SELECT 2 AS id
UNION 
SELECT 3 AS id
UNION 
SELECT 4 AS id
UNION 
SELECT 5 AS id
) Tab


/* Using CROSS APPLY 
Query cost relative to the batch 17%
*/    
SELECT   T1.id, 
         T2.CumSum 
FROM     #TMP T1 
         CROSS APPLY ( 
         SELECT   SUM(T2.id) AS CumSum 
         FROM     #TMP T2 
         WHERE    T1.id >= T2.id
         ) T2

/* Using INNER JOIN 
Query cost relative to the batch 46%
*/
SELECT   T1.id, 
         SUM(T2.id) CumSum
FROM     #TMP T1
         INNER JOIN #TMP T2
                 ON T1.id > = T2.id
GROUP BY T1.id

/* Using OVER clause
Query cost relative to the batch 37%
*/
SELECT   T1.id, 
         SUM(T1.id) OVER( PARTITION BY id)
FROM     #TMP T1

Output:-
  id       CumSum
-------   ------- 
   1         1
   2         3
   3         6
   4         10
   5         15

答案 6 :(得分:3)

Select *, (Select SUM(SOMENUMT) From @t S Where S.id <= M.id) From @t M

答案 7 :(得分:2)

这篇优秀文章提供了更快的CTE实施: http://weblogs.sqlteam.com/mladenp/archive/2009/07/28/SQL-Server-2005-Fast-Running-Totals.aspx

此线程中的问题可以表示如下:     

    DECLARE @RT INT
    SELECT @RT = 0

    ;
    WITH  abcd
            AS ( SELECT TOP 100 percent
                        id
                       ,SomeNumt
                       ,MySum
                       order by id
               )
      update abcd
      set @RT = MySum = @RT + SomeNumt
      output inserted.*

DECLARE @RT INT SELECT @RT = 0 ; WITH abcd AS ( SELECT TOP 100 percent id ,SomeNumt ,MySum order by id ) update abcd set @RT = MySum = @RT + SomeNumt output inserted.*

答案 8 :(得分:1)

创建表格后

select 
    A.id, A.SomeNumt, SUM(B.SomeNumt) as sum
    from @t A, @t B where A.id >= B.id
    group by A.id, A.SomeNumt

order by A.id

答案 9 :(得分:1)

上面(Pre-SQL12)我们看到这样的例子: -

SELECT
    T1.id, SUM(T2.id) AS CumSum
FROM 
    #TMP T1
    JOIN #TMP T2 ON T2.id < = T1.id
GROUP BY
    T1.id

效率更高......

SELECT
    T1.id, SUM(T2.id) + T1.id AS CumSum
FROM 
    #TMP T1
    JOIN #TMP T2 ON T2.id < T1.id
GROUP BY
    T1.id

答案 10 :(得分:0)

试试这个

select 
    t.id,
    t.SomeNumt, 
    sum(t.SomeNumt) Over (Order by t.id asc Rows Between Unbounded Preceding and Current Row) as cum
from 
    @t t 
group by
    t.id,
    t.SomeNumt
order by
    t.id asc;

答案 11 :(得分:0)

试试这个:

CREATE TABLE #t(
 [name] varchar NULL,
 [val] [int] NULL,
 [ID] [int] NULL
) ON [PRIMARY]

insert into #t (id,name,val) values
 (1,'A',10), (2,'B',20), (3,'C',30)

select t1.id, t1.val, SUM(t2.val) as cumSum
 from #t t1 inner join #t t2 on t1.id >= t2.id
 group by t1.id, t1.val order by t1.id

答案 12 :(得分:0)

SQL解决方案,它结合了“无限制前进和当前行之间的行”#34;和&#34; SUM&#34;完成了我想要实现的目标。 非常感谢你!

如果它可以帮助任何人,这是我的情况。每当制造商被发现为&#34; Some Maker&#34;时,我想在列中累积+1。 (例)。如果没有,则没有增量但显示先前的增量结果。

所以这段SQL:

SUM( CASE [rmaker] WHEN 'Some Maker' THEN  1 ELSE 0 END) 
OVER 
(PARTITION BY UserID ORDER BY UserID,[rrank] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Cumul_CNT

允许我得到这样的东西:

User 1  Rank1   MakerA      0  
User 1  Rank2   MakerB      0  
User 1  Rank3   Some Maker  1  
User 1  Rank4   Some Maker  2  
User 1  Rank5   MakerC      2
User 1  Rank6   Some Maker  3  
User 2  Rank1   MakerA      0  
User 2  Rank2   SomeMaker   1  

上述说明:它开始计算&#34;某个制造商&#34; 0,找到了一些Maker,我们做+1。对于用户1,发现了MakerC,所以我们不做+1,而是将Some Maker的垂直计数固定为2直到下一行。 分区是由用户进行的,因此当我们更改用户时,累计计数会回到零。

我在工作,我不希望这个答案有任何优点,只要说谢谢并展示我的例子,以防有人处于同样的情况。我试图将SUM和PARTITION结合起来,但结合了惊人的语法&#34;在无限制的前进行和当前的行之间行驶#34;完成任务。

谢谢! Groaker

答案 13 :(得分:0)

使用跟随查询不使用任何类型的JOIN累积工资:

SELECT * , (
  SELECT SUM( salary ) 
  FROM  `abc` AS table1
  WHERE table1.ID <=  `abc`.ID
    AND table1.name =  `abc`.Name
) AS cum
FROM  `abc` 
ORDER BY Name

答案 14 :(得分:0)

您可以使用此简单查询进行渐进式计算:

select 
   id
  ,SomeNumt
  ,sum(SomeNumt) over(order by id ROWS between UNBOUNDED PRECEDING and CURRENT ROW) as CumSrome
from @t

答案 15 :(得分:0)

对于Ex:如果您有一个包含两列的表,其中第一列是ID,第二列是数字,并希望找出累积和。

SELECT ID,Number,SUM(Number)OVER(ORDER BY ID) FROM T
相关问题