2013-04-03 3 views
0

Je souhaite mettre à jour la valeur de ligne qui a une partie de la valeur de ligne précédente. (Fondamentalement, j'ai besoin de trouver un effet de report).Mise à jour de la ligne SQL sur la base des valeurs de la ligne précédente

J'utilise While loop ou cursor pour faire la même chose mais cela prend beaucoup de temps car l'instruction de mise à jour exécute le nombre de lignes fois.

S'il vous plaît me suggérer un bon moyen efficace pour savoir effet de report. Ci-dessous est l'exemple de dataset avec 0,2 effet de report.

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 

et ainsi de suite

Je veux un plus plus que donné dans l'exemple ci-dessous

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) 

et ainsi de suite ... Il peut y avoir à une ou plusieurs variables clés comme la marque est ici qui divise l'ensemble complet en deux ou plusieurs sous-ensembles.

+0

vous pouvez faire en 1ère sélection stmnt pour la dernière valeur, où u obtenir la dernière carry_over_Value puis insérez ou mettre à jour –

Répondre

1

Je suppose que l'ordre est défini par WeekNumber, et que cela est séquentielle sans lacunes. Plutôt que de faire une mise à jour, pourquoi ne pas simplement effectuer les calculs au cours de sélection (cette façon, vous n'avez pas à vous soucier du calcul étant hors de date):

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) 

Résultats:

WeekNumber Var1  CarryOver 
----------- ----------- --------------------------------------- 
1   10   10.0000 
2   30   32.0000 
3   80   86.4000 

UPDATE Version:

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 

Mais je le répète, je vous recommande de le faire contre à moins d'une problème de performance prouvé pour exécuter simplement le SELECT lors d'une utilisation normale - tout autre UPDATE s à la table maintenant besoin de ce UPDATE être exécuté immédiatement après, de sorte que vous ajoutez un coût de performance considérable pour chaque UPDATE.


Avec Brand ajouté:

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

Nous vous remercions de votre réponse. .right weeknumber est utilisé pour commander sans espace .. La solution que vous donnez prendra beaucoup de temps quand je l'exécute sur plus de 200 milliers de lignes .. – user2239073

+0

@ user2239073 - bien, si vous voulez vraiment le stocker, vous pouvez écrire une 'UPDATE' qui' JOIN ''CarryOvers' de retour à la table d'origine et affecter la valeur de retour - mais à quelle fréquence interrogez-vous cette table pour toutes les 200000 lignes? –

+0

@ Damien_The_Unbeliever quand je suis en cours d'exécution du code ci-dessus pour plus de 100 lignes que je reçois erreur: Msg 530, Niveau 16, État 1, 1 ligne L'instruction terminée. La récursivité maximale 100 a été épuisée avant la fin de l'instruction. – user2239073

1

Votre question n'est pas claire. Mais pensez à utiliser TRIGGERS

Je ne suis pas sûr de ce fonctionnement.

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

Salut Santosh, je veux mettre à jour dynamiquement mes lignes qui dépendent des valeurs de ligne précédentes. Par exemple, si la valeur variable de la ligne 1 est 20 alors sa valeur correspondante doit être 20 et la valeur variable de la ligne 2 est 30 alors sa valeur correspondante devrait être 30 + 0,2 * 20, Si le pourcentage pris est .20 – user2239073

Questions connexes