2013-04-03 57 views
0

我想要更新具有來自上一行值一部分的行值。 (基本上我需要找到結轉效應)。根據前一行的值更新SQL行

我正在使用While loopcursor來做同樣的事情,但它需要很多時間,因爲update語句運行的是行數倍。

請給我一個很好的方法來找出結轉效應。以下是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) 

等等... 有可能以一個或多個關鍵變量,品牌是這裏它將整個集合分成兩個或更多個子集。

+0

您可以通過第一個選擇stmnt的最後一個值,其中u得到最後carry_over_Value然後插入或更新 –

回答

1

我假定排序是由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 - 表中的任何其他UPDATE現在需要此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) 
+0

感謝您的回覆。 .right weeknumber用於排序沒有差距..當我運行在超過20萬行的時候,你給的解決方案將花費很多時間.. – user2239073

+0

@ user2239073 - 好吧,如果你真的想存儲它,你可以寫一個'UPDATE',把'JOIN's'CarryOvers'返回到原始表並賦值 - 但是你多長時間查詢這個表的所有200000行? –

+0

@ Damien_The_Unbeliever當我運行上面的代碼超過100行時我收到錯誤:消息530,級別16,狀態1,行1 聲明終止。報表完成前,最大遞歸100已用盡。 – user2239073

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 
+0

嗨桑托斯,我要動態更新我行做哪些依賴於先前的行值。例如,如果第1行中的變量值爲20,那麼其相應的值應爲20,第2行中的變量值爲30,則其相應值應爲30 + 0.2 * 20,如果所用的百分比爲.20 – user2239073

相關問題