根据上一行的值更新SQL行

时间:2013-04-03 06:16:08

标签: sql-server-2008 insert-update

我想更新具有前一行值的一部分的行值。 (基本上我需要找到结转效应)。

我正在使用While loopcursor来执行相同操作,但由于更新语句运行行数次,因此需要花费大量时间。

请建议我找出结转效果的有效方法。以下是具有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在这里将整个集合划分为两个或更多个子集。

2 个答案:

答案 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