1

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

我正在使用While loopcursor执行相同的操作,但是由于更新语句运行了行数,因此需要花费很多时间。

请建议我一个很好的有效方法来找出结转效果。下面是dataset带有 0.2 结转效果的示例。

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 在这里将完整的集合划分为两个或多个子集。

4

2 回答 2

2

我假设排序由 定义WeekNumber,并且这是连续的,没有间隙。与其进行更新,不如只在选择期间执行计算(这样,您不必担心计算已过时):

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在正常使用期间运行它是一个已证明的性能问题 - 现在表中的任何其他UPDATEs 都需要UPDATE在之后立即运行它,所以你增加了相当大的性能成本对于每个UPDATE.


添加Brand

declare @t table (Brand char(1),WeekNumber int, Var1 int)
insert into @t (Brand,WeekNumber, Var1) values
('x',1,           10),
('x',2,           30),
('x',3,           80),
('y',1,40),
('y',2,50)

;with CarryOvers as (
    select Brand,WeekNumber,Var1,CONVERT(decimal(38,4),Var1) as CarryOver from @t where WeekNumber=1
    union all
    select t.Brand,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 and t.Brand = co.Brand
)
select * from CarryOvers
order by Brand,WeekNumber option (maxrecursion 0)
于 2013-04-03T06:46:41.687 回答
1

你的问题不清楚。但考虑使用触发器

我不确定这个工作。

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
于 2013-04-03T06:25:44.240 回答