获取所有先前值的总和? - 到目前为止的总数? [复制]
Posted
技术标签:
【中文标题】获取所有先前值的总和? - 到目前为止的总数? [复制]【英文标题】:Get sum of all previous values? - Total so far? [duplicate] 【发布时间】:2012-01-03 00:28:34 【问题描述】:可能重复:How do I calculate a running total in SQL without using a cursor?
这有点难以解释,所以我会用一个例子来展示我想要的:
假设我们有一个名为 MonthProfit
的表:
[MonthId][Profit]
1, 10 -- January
2, 20 -- February
3, 30
4, 40
5, 50
6, 60
7, 70
8, 80
9, 90
10, 100
11, 110
12, 120 -- December
profit
列代表当月的利润。
但是,如果我们 1 月份有 10 个利润,2 月份有 20 个利润,那么 2 月份我们的总利润是 30。
所以我想创建一个显示以下内容的视图:
[MonthId][Profit][ProfitTotal]
1, 10, 10 -- January
2, 20, 30 -- February
3, 30, 60
4, 40, 100
5, 50, 150
6, 60, 210
7, 70, 280
8, 80, 360
9, 90, 450
10, 100, 550
11, 110, 660
12, 120, 780 -- December
我现在解决它的方法是这样的:
SELECT [MonthId]
,[Profit]
, (SELECT SUM([Profit])
FROM MonthProfit
WHERE [MonthId] <= outer.[MonthId]) as ProfitTotal
FROM MonthProfit as outer
但是,我认为这很慢,因为它必须一直重新计算所有内容,而且对我来说似乎不是很优雅。有没有“好”的方法来做到这一点?
【问题讨论】:
还有***.com/questions/814054/… 只要搜索“Running total SQL”,你就会得到很多点击率。 【参考方案1】:这似乎不是一个非常优雅的选择,但它可以正常工作。
如果你想提高,你有几个选择:
-
在表中创建第三列(ProfitTotal),该列将在插入/更新值时更新(触发),或者如果您想在选择时进行更新;
创建索引以使其更快;
更新表格统计信息。
【讨论】:
【参考方案2】:试试下面这样的方法,乍一看还不错:-)。
create table #tab ([MonthId] int, [Profit] int)
insert into #tab select 1, 10 -- January
insert into #tab select 2, 20 -- February
insert into #tab select 3, 30
insert into #tab select 4, 40
insert into #tab select 5, 50
insert into #tab select 6, 60
insert into #tab select 7, 70
insert into #tab select 8, 80
insert into #tab select 9, 90
insert into #tab select 10, 100
insert into #tab select 11, 110
insert into #tab select 12, 120 -- December
select t.*, t3.total
from #tab t
join (
select t1.monthId,
sum(t2.profit) as total
from #tab t1
join #tab t2 on t1.monthId >= t2.monthId
group by t1.monthId
) t3 on t.monthId = t3.monthId
【讨论】:
【参考方案3】:我在这里尝试了一个小示例供您参考,这会根据要求生成结果
CREATE TABLE [dbo].[tbl_TotalPrevious](
[id] [int] IDENTITY(1,1) NOT NULL,
[name] [varchar](50) NOT NULL,
[values] [bigint] NOT NULL)
向表格中插入数据
insert into tbl_TotalPrevious values ('A', 10)
insert into tbl_TotalPrevious values ('B', 20)
insert into tbl_TotalPrevious values ('C', 10)
insert into tbl_TotalPrevious values ('D', 10)
insert into tbl_TotalPrevious values ('E', 10)
insert into tbl_TotalPrevious values ('F', 10)
insert into tbl_TotalPrevious values ('G', 10)
insert into tbl_TotalPrevious values ('H', 10)
insert into tbl_TotalPrevious values ('I', 10)
insert into tbl_TotalPrevious values ('J', 10)
insert into tbl_TotalPrevious values ('K', 10)
insert into tbl_TotalPrevious values ('L', 10)
insert into tbl_TotalPrevious values ('M', 10)
insert into tbl_TotalPrevious values ('N', 10)
insert into tbl_TotalPrevious values ('O', 10)
insert into tbl_TotalPrevious values ('P', 10)
insert into tbl_TotalPrevious values ('Q', 10)
insert into tbl_TotalPrevious values ('R', 10)
insert into tbl_TotalPrevious values ('S', 10)
insert into tbl_TotalPrevious values ('T', 10)
insert into tbl_TotalPrevious values ('U', 10)
insert into tbl_TotalPrevious values ('V', 10)
insert into tbl_TotalPrevious values ('W', 10)
insert into tbl_TotalPrevious values ('X', 10)
insert into tbl_TotalPrevious values ('Y', 10)
创建一个函数,例如。
ALTER FUNCTION testtotal
(
@id int
)
RETURNS int
AS
BEGIN
DECLARE @Result int
SELECT @Result = (SELECT SUM([values])
FROM tbl_TotalPrevious
WHERE [id] <= @id)
RETURN @Result
END
GO
由单个查询生成的结果
SELECT [id],[values], (dbo.testtotal(id)) as TotalVals FROM tbl_TotalPrevious
希望以上内容能够解决您的时间问题,并根据需要更快地生成数据。
【讨论】:
这不和我的子查询完全一样吗?只封装成一个函数? 但是这样做仍然会因为一个函数而减少时间和表扫描。但我认为你应该为你拥有的实时数据实施并测试你的执行计划。【参考方案4】:declare @MonthProfit table
(
[MonthId] int,
[Profit] int
)
insert into @MonthProfit values
(1, 10),(2, 20),(3, 30),(4, 40),
(5, 50),(6, 60),(7, 70),(8, 80),
(9, 90),(10, 100),(11, 110),(12, 120)
;with C as
(
select M.MonthId,
M.Profit
from @MonthProfit as M
where M.MonthId = 1
union all
select M.MonthId,
C.Profit + M.Profit
from @MonthProfit as M
inner join C
on M.MonthId = C.MonthId + 1
)
select C.MonthId,
C.Profit
from C
order by C.MonthId
【讨论】:
以上是关于获取所有先前值的总和? - 到目前为止的总数? [复制]的主要内容,如果未能解决你的问题,请参考以下文章