考虑此表:
create table x (id int, total int, diff int)
这个数据:
[1, 100, 20]
[2, null, 30]
[3, null, -15]
[4, null, 4]
…
我需要计算"总数"根据前一行的列。
这意味着最终数据看起来应该是这样的:
[1, 100, 20]
[2, 120, 30]
[3, 150, -15]
[4, 135, 4]
…
这样做最有效的方法是什么?
答案 0 :(得分:2)
我不太确定这个tbh的性能,所以你应该测试一下,但这是一种方式。我确定还有其他方法,所以这是一种可能性。正如我所说,表现将是我的主要关注点。
DECLARE @Data TABLE (ID INTEGER PRIMARY KEY, Total INTEGER, Diff INTEGER)
INSERT @Data VALUES (1, 100, 20)
INSERT @Data VALUES (2, NULL, 30)
INSERT @Data VALUES (3, NULL, -15)
INSERT @Data VALUES (4, NULL, 4)
DECLARE @StartingTotal INTEGER
SELECT @StartingTotal = Total FROM @Data WHERE ID = 1
UPDATE d
SET d.Total = @StartingTotal + TotalDiff
FROM @Data d
CROSS APPLY (SELECT SUM(Diff) TotalDiff FROM @Data d2 WHERE d2.ID < d.ID) x
WHERE d.Total IS NULL
SELECT * FROM @Data
答案 1 :(得分:2)
好的,这是另一种选择。作为一个单独的答案添加,因为它是一个完全不同的方法。
这个假设是ID中没有间隙 - 这可能不太现实,但它证明了这种方法。如果ID中存在间隙,那么只需要对JOIN进行一些调整即可。
DECLARE @Data TABLE (ID INTEGER PRIMARY KEY, Total INTEGER, Diff INTEGER)
INSERT @Data VALUES (1, 100, 20)
INSERT @Data VALUES (2, NULL, 30)
INSERT @Data VALUES (3, NULL, -15)
INSERT @Data VALUES (4, NULL, 4)
DECLARE @PreviousTotal INTEGER
SELECT @PreviousTotal = Total
FROM @Data
WHERE ID = 1
UPDATE d
SET @PreviousTotal = d.Total = @PreviousTotal + d2.Diff
FROM @Data d
JOIN @Data d2 ON d.ID = d2.Id + 1
SELECT * FROM @Data
答案 2 :(得分:0)
假设样本结果错误,并且它应该像评论中的marc_s
一样,你可以这样做:
第一条记录:
INSERT into X Values(1, 100, 20)
然后针对所有其他人(在第一列和最后一列中包含相应的id
和diff
值):
INSERT into X SELECT TOP 1 2, total+diff, 30 FROM X ORDER BY id desc
不太好,但它确实有效。
答案 3 :(得分:0)
我通常不建议使用游标,但在这种情况下,它可能是一个不错的选择。 如果您担心性能,您需要测试这里给出的答案,以找出最适合您的方法。最佳解决方案可能因表中的行数而异。
declare @T as table (id int, total int, diff int)
insert into @T values (1, 100, 20)
insert into @T values (2, null, 30)
insert into @T values (3, null, -15)
insert into @T values (4, null, 4)
declare @id int
declare @diff int
declare @total int
select @total = total
from @T
where id = 1
declare cT cursor for select id, diff from @T order by id
open cT
fetch next from cT into @id, @diff
while (@@FETCH_STATUS <> -1)
begin
update @T
set total = @total
where id = @id
set @total = @total + @diff
fetch next from cT into @id, @diff
end
close cT
deallocate cT
select *
from @T