我想更新具有前一行值的一部分的行值。 (基本上我需要找到结转效应)。
我正在使用While loop
或cursor
来执行相同操作,但由于更新语句运行行数次,因此需要花费大量时间。
请建议我找出结转效果的有效方法。以下是具有0.2结转效应的dataset
的示例。
WeekNumber Var1 carry_over_effect_0.2
1 10 10
2 30 30+0.2*10
3 80 80+(30+0.2*10)*0.2
等等
我想在下面的示例中再添加一个
Brand WeekNumber Var1 carry_over_effect_0.2
x 1 10 10
x 2 30 30+0.2*10
x 3 80 80+(30+0.2*10)*0.2
y 1 40 40
y 2 50 50 + (40*0.2)
依旧...... 可能有一个或多个关键变量,因为Brand在这里将整个集合划分为两个或更多个子集。
答案 0 :(得分:2)
我假设排序由WeekNumber
定义,并且这是顺序的,没有间隙。而不是进行更新,为什么不在select期间执行计算(这样,您不必担心计算过时):
declare @t table (WeekNumber int, Var1 int)
insert into @t (WeekNumber, Var1) values
(1, 10),
(2, 30),
(3, 80)
;with CarryOvers as (
select WeekNumber,Var1,CONVERT(decimal(38,4),Var1) as CarryOver from @t where WeekNumber=1
union all
select t.WeekNumber,t.Var1,CONVERT(decimal(38,4),t.Var1 + (0.2*co.CarryOver))
from @t t inner join CarryOvers co on t.WeekNumber = co.WeekNumber+1
)
select * from CarryOvers option (maxrecursion 0)
结果:
WeekNumber Var1 CarryOver
----------- ----------- ---------------------------------------
1 10 10.0000
2 30 32.0000
3 80 86.4000
UPDATE
版本:
declare @t table (WeekNumber int, Var1 int,CarryOver decimal(38,4))
insert into @t (WeekNumber, Var1) values
(1, 10),
(2, 30),
(3, 80)
;with CarryOvers as (
select WeekNumber,Var1,CONVERT(decimal(38,4),Var1) as CarryOver from @t where WeekNumber=1
union all
select t.WeekNumber,t.Var1,CONVERT(decimal(38,4),t.Var1 + (0.2*co.CarryOver))
from @t t inner join CarryOvers co on t.WeekNumber = co.WeekNumber+1
)
update t set CarryOver = co.CarryOver
from @t t inner join CarryOvers co on t.WeekNumber = co.WeekNumber
option (maxrecursion 0)
select * from @t
但是我会重复我建议不要这样做,除非在正常使用期间运行SELECT
是一个经过验证的性能问题 - 表中的任何其他UPDATE
现在需要这个{{ 1}}之后立即运行,因此您为每个UPDATE
添加了相当大的性能成本。
添加UPDATE
:
Brand
答案 1 :(得分:1)
你的问题不明确。但考虑使用TRIGGERS
我不确定这是否有效。
CREATE TRIGGER NAME
BEFORE INSERT INTO TABLE_NAME
FOR EACH ROW BEGIN
WHERE (SELECT COUNT(*) FROM TABLE_nAME) > 0
BEGIN
INSERT INTO TABLE-NAME
SELECT NEW.WEEKNUMBER, NEW.VAR1, (NEW.VAR1+S.CARRY_OVER_EFFECT *0.2) AS CARRY_OVER_EFFECT
FROM
TABLE-NAME S
WHERE S.WEEKNUMBER + 1= NEW.WEEK_NUMBER;
END