我需要在ms-sql server中获取一列的累积(运行)总数。即如果有一个名为“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;
提前致谢。
答案 0 :(得分:5)
从2012年开始支持相同的查询。在旧版本中,有几种方法。请参阅此http://www.sqlperformance.com/2012/07/t-sql-queries/running-totals
答案 1 :(得分:2)
试试这个:
您只需加入相同的表格就可以获得累积金额
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
答案 2 :(得分:1)
你说没有加入,申请怎么样? ;)
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 :(得分:1)
检查递归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
答案 4 :(得分:0)
使用递归CTE来实现这一目标。
答案 5 :(得分:0)
JUSt做一个连接似乎不保证顺序,但最终答案确定:
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