获取所有先前值的总和? - 到目前为止的总数? [复制]

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

【讨论】:

以上是关于获取所有先前值的总和? - 到目前为止的总数? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV:获取 Mat 值的总数

获取Rails模型中关联列的总和

使用 Graphql 和 Amplify/AppSync 基于先前值的突变

基于另一列的每个值的列值总和,然后除以总数

通过分页获取结果总数

SQL 查找 MAX 值的总和