2011-11-21 48 views
7

thể trùng lặp:
How do I calculate a running total in SQL without using a cursor?Nhận tổng của tất cả các giá trị trước đó? - Tổng số cho đến nay?

Đó là một chút khó khăn để giải thích, vì vậy tôi sẽ hiển thị những gì tôi muốn với một ví dụ:

phép nói rằng chúng ta có bảng sau có tên 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 

Cột profit thể hiện lợi nhuận cho tháng đó.

Tuy nhiên, nếu chúng tôi có 10 lợi nhuận vào tháng Giêng, và 20 trong tháng, vào tháng Hai chúng tôi có một lợi nhuận tổng cộng 30.

vì vậy tôi muốn tạo một cái nhìn thể hiện như sau:

[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 

những gì tôi đã làm tại để giải quyết nó, là một cái nhìn như thế này:

SELECT [MonthId] 
     ,[Profit] 
     , (SELECT SUM([Profit]) 
     FROM MonthProfit 
     WHERE [MonthId] <= outer.[MonthId]) as ProfitTotal 
FROM MonthProfit as outer 

Tuy nhiên, tôi cho rằng điều này là khá chậm bởi vì nó có để kể lại tất cả mọi thứ trong mọi lúc, và nó dường như không đã ry tao nhã với tôi. Có cách nào "tốt" để làm điều này không?

+2

cũng http://stackoverflow.com/questions/814054/complicated-sql-query-for-a-running-total-column – JNK

+2

Chỉ cần tìm kiếm cho "Running tổng SQL" và bạn sẽ nhận được nhiều lượt truy cập về điều này. – JNK

Trả lời

3

Tôi đã thử một ví dụ nhỏ ở đây để bạn tham khảo này tạo ra các kết quả theo yêu cầu

CREATE TABLE [dbo].[tbl_TotalPrevious](
[id] [int] IDENTITY(1,1) NOT NULL, 
[name] [varchar](50) NOT NULL, 
[values] [bigint] NOT NULL) 

INSERT dữ liệu vào bảng

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) 

Tạo một chức năng ví dụ.

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 

KẾT QUẢ tạo từ truy vấn SINGLE

SELECT [id],[values], (dbo.testtotal(id)) as TotalVals FROM tbl_TotalPrevious 

hy vọng ở trên giải quyết MỤC ĐÍCH CỦA BẠN VỚI vấn đề thời gian và tạo ra dữ liệu nhanh hơn theo yêu cầu.

RESULTS IMAGE

+1

Không thực hiện chính xác như truy vấn phụ của tôi? Chỉ đóng gói vào một chức năng? –

+0

Nhưng làm như vậy sẽ giảm thời gian và quét bảng do chức năng. nhưng tôi nghĩ bạn nên triển khai và thử nghiệm kế hoạch thực hiện cho dữ liệu trực tiếp mà bạn có. – Murtaza

-1

Điều đó có vẻ là một lựa chọn không phải rất thanh lịch nhưng nó hoạt động bình thường.

Nếu bạn muốn cải thiện, bạn có nhiều lựa chọn:

  1. tạo ra một cột thứ ba trong bảng (các ProfitTotal) sẽ được cập nhật (kích hoạt) trên chèn/giá trị cập nhật hoặc nếu bạn muốn làm cho nó vào lựa chọn;
  2. Tạo chỉ mục để làm cho chỉ số nhanh hơn;
  3. Cập nhật thống kê bảng.
0

Hãy thử một cái gì đó như thế này bên dưới, thoạt nhìn có vẻ tốt :-).

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 
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 
Các vấn đề liên quan