如何获得累计总和
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
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小提琴示例
产量
| ID | SOMENUMT | SUM | ----------------------- | 1 | 10 | 10 | | 2 | 12 | 22 | | 3 | 3 | 25 | | 4 | 15 | 40 | | 5 | 23 | 63 |
编辑:这是一个广泛的解决方案,将在大多数数据库平台上工作。 如果有更好的解决方案可用于您的特定平台(例如gareth's),请使用它!
最新版本的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团队线程。
一个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
按照公共需求提供—-
让我们先创建一个虚拟数据表 – >
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加入)
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
期望的结果
ID SomeValue CumlativeSumValue 1 10 10 2 2 12 3 6 18 4 10 28 Drop Table CumulativeSum
清除虚拟表
对于SQL Server 2012,可能很简单:
SELECT id, SomeNumt, sum(SomeNumt) OVER (ORDER BY id) as CumSrome FROM @t
因为默认情况下SUM
的ORDER BY
子句表示窗口框架的RANGE UNBOUNDED PRECEDING AND CURRENT ROW
( https://msdn.microsoft.com/zh-cn/library/ms189461.aspx上的; “General Notes”)
迟到的答案,但显示多一个可能性…
使用CROSS APPLY
逻辑可以更加优化累计和生成。
分析实际的查询计划时比INNER JOIN
& 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
在这个出色的文章中有一个更快的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.*
Select *, (Select SUM(SOMENUMT) From @t S Where S.id <= M.id) From @t M
一旦表被创建 –
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
上面(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
尝试这个
select t.id, t.SomeNumt, sum(t.SomeNumt) Over (Order by t.id asc Rows Between Unbounded Preceding and Current Row) as cum from @tt group by t.id, t.SomeNumt order by t.id asc;
尝试这个:
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
SQL解决方案结合了“无界的先行和当前行之间的行”和“SUM”正是我想要实现的。 非常感谢!
如果能帮助任何人,这是我的情况。 每当制造商被找到为“Some Maker”(例子)时,我想在一列中累积+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
上面的解释:用“0”开始“某个制造商”的计数,找到一些制造商,我们做+1。 对于用户1,MakerC被发现,所以我们不做+1,而是一些制造商的垂直计数是坚持到2,直到下一行。 分区是由用户,所以当我们改变用户时,累计计数回到零。
我在工作,我不想在这个答案的任何优点,只是说谢谢,并显示我的例子,以防有人在相同的情况下。 我正在尝试将SUM和PARTITION结合起来,但是令人惊叹的语法“ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW”完成了这个任务。
谢谢! Groaker
不使用任何类型的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