获取所有先前值的总和? - 到目前为止总计?

时间:2011-11-21 13:58:56

标签: sql tsql recursion

  

可能重复:
  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

然而,我认为这很慢,因为它必须一直重述所有内容,而且对我来说似乎并不优雅。有没有“好”的方法呢?

4 个答案:

答案 0 :(得分: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 

希望上面的问题能够解决您的时间问题并根据需要更快地生成数据。

RESULTS IMAGE

答案 1 :(得分:0)

尝试下面这样的事情,乍一看看很好: - )。

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

答案 2 :(得分:0)

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

答案 3 :(得分:-1)

这似乎是一个不太优雅的选择,但它运作正常。

如果你想改进,你有几个选择:

  1. 在表格中创建第三列(ProfitTotal),这些列将在插入/更新值上更新(触发),或者如果您想在选择中进行更新;
  2. 创建索引以加快速度;
  3. 更新表统计信息。