2013-03-14 2 views
1

J'ai donc cette requête qui recherche ID par ID et calcule le coût en conséquence. Mais est très lent et je voudrais comprendre comment je pourrais le convertir en une opération basée sur un ensemble. Donc en fonction de notre état, nous calculons nos coûts modélisés différemment.convertir le curseur en une opération basée sur un ensemble

Lorsque l'utilisateur met à jour un pilote, nous pouvons exécuter une mise à jour sur la colonne du pilote en entier en fonction de l'endroit où il a été modifié.

Mais quand il s'agit de calculer le coût modélisé. Nous le faisons ligne par ligne comme le coût fixe diffère, puis diviser par mois. J'ai collé le code ci-dessous. Y a-t-il encore un moyen d'y parvenir par une opération basée sur un ensemble?

D'abord, nous mettons à jour les pilotes de la même table en fonction de ce que la valeur a changé en utilisant une mise à jour et mettre à jour la ligne de coût modélisé par ligne (ce qui est vraiment lent)

code:

SELECT @rowCounter = 1, @totalrows = @@ROWCOUNT 

WHILE @rowCounter <= @totalrows 
    BEGIN 

     SELECT @currentId = tempId 
     FROM @temp 
     WHERE row = @rowCounter  

     SELECT 
       @newModeledCost = 
       case when not exists (select 1 from dbo.DIMSTD_SCENARIO where SCENARIO0_Name = SCENARIO and SCENARIO2_Name = 'Model') then 
       ISNULL(DriverValue1,0)*ISNULL(DriverValue2,0)*ISNULL(UnitA,0)*ISNULL(UnitB,0)+ISNULL(FixedCost,0) 
       -- normal allocation for all scenarios 
       else 
       (ISNULL(unita,0) * (ISNULL(DriverValue1,0)/ISNULL(NULLIF(DriverValue2,0),1))* ISNULL(UnitB,0))+ISNULL(FixedCost,0) 
       --(ISNULL(unita,0) * (ISNULL(DriverValue1,0)/ISNULL(DriverValue2,0))*ISNULL(UnitB,0))+ISNULL(FixedCost,0) 
       -- allocation for model scenarios 
       end 
       ,          
       @oldModeledCost = ISNULL(ModeledCost,0), 
       @newOct = (ISNULL(@newModeledCost,0) * (ISNULL(Oct, 0) /ISNULL(NULLIF(@oldModeledCost,0),1))), 
       @newNov = (ISNULL(@newModeledCost,0) * (ISNULL(Nov, 0) /ISNULL(NULLIF(@oldModeledCost,0),1))), 
       @newDec = (ISNULL(@newModeledCost,0) * (ISNULL(Dec, 0) /ISNULL(NULLIF(@oldModeledCost,0),1))), 
       @newJan = (ISNULL(@newModeledCost,0) * (ISNULL(Jan, 0) /ISNULL(NULLIF(@oldModeledCost,0),1))), 
       @newFeb = (ISNULL(@newModeledCost,0) * (ISNULL(Feb, 0) /ISNULL(NULLIF(@oldModeledCost,0),1))), 
       @newMar = (ISNULL(@newModeledCost,0) * (ISNULL(Mar, 0) /ISNULL(NULLIF(@oldModeledCost,0),1))), 
       @newApr = (ISNULL(@newModeledCost,0) * (ISNULL(Apr, 0) /ISNULL(NULLIF(@oldModeledCost,0),1))), 
       @newMay = (ISNULL(@newModeledCost,0) * (ISNULL(May, 0) /ISNULL(NULLIF(@oldModeledCost,0),1))), 
       @newJun = (ISNULL(@newModeledCost,0) * (ISNULL(Jun, 0) /ISNULL(NULLIF(@oldModeledCost,0),1))), 
       @newJul = (ISNULL(@newModeledCost,0) * (ISNULL(Jul, 0) /ISNULL(NULLIF(@oldModeledCost,0),1))), 
       @newAug = (ISNULL(@newModeledCost,0) * (ISNULL(Aug, 0) /ISNULL(NULLIF(@oldModeledCost,0),1))), 
       @newSep = (ISNULL(@newModeledCost,0) * (ISNULL(Sep, 0) /ISNULL(NULLIF(@oldModeledCost,0),1))) 
     FROM dbo.TBF_BUDGETExpenses 
     WHERE BudgetId = @currentId 
     --and not exists (select 1 from dbo.DIMSTD_SCENARIO where SCENARIO0_Name = SCENARIO and SCENARIO2_Name = 'Model') 

     UPDATE dbo.TBF_BUDGETExpenses 
     SET ModeledCost = @newModeledCost, 
      Oct = @newOct, 
      Nov = @newNov, 
      Dec = @newDec, 
      Jan = @newJan, 
      Feb = @newFeb, 
      Mar = @newMar, 
      Apr = @newApr, 
      May = @newMay, 
      Jun = @newJun, 
      Jul = @newJul, 
      Aug = @newAug, 
      Sep = @newSep, 
      Username = 'Cascade', 
      lastmodified = getdate()     
     WHERE BudgetId = @currentId 
     AND @oldModeledCost <> 0 

     Print 'Record Update ' + CAST(@currentId AS VARCHAR(15)) 

     SET @rowCounter = @rowCounter + 1 

END 

Répondre

0

Pour vous cas, le fonctionnement sans aucun doute mis est meilleur et possible, mais La meilleure approche que je puisse penser est de ne pas utiliser de requête, mais d'utiliser le DDL de la table. Lorsque vous créez une table, vous pouvez créer des colonnes calculées avec persisted. Comme vos colonnes de douze mois, ils peuvent être des colonnes calculées, et tous les facteurs paticipate dans votre calcul informatique tout à partir de la même table. Voici le lien: http://msdn.microsoft.com/en-us/library/ms186241.aspx

0

Il est difficile de le valider sans un schéma complet, des données de test et des résultats attendus. Ceci est un reprofit basé sur un ensemble rapide de votre mise à jour actuelle. Remarque: J'ai déplacé votre ModeledCost CASE dans une sous-requête juste pour éviter de le répéter dans chaque ensemble de colonnes. A vous de voir si cela a un sens logique ou non ... Je suppose que BudgetId est le PK.

Exécutez la mise à jour en tant que SELECT pour confirmer sa production ResultSet souhaitée:

select t.BudgetId, 
     -- 
     Oct = (ISNULL(new.ModeledCost,0) * (ISNULL(Oct, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     Nov = (ISNULL(new.ModeledCost,0) * (ISNULL(Nov, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     Dec = (ISNULL(new.ModeledCost,0) * (ISNULL(Dec, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     Jan = (ISNULL(new.ModeledCost,0) * (ISNULL(Jan, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     Feb = (ISNULL(new.ModeledCost,0) * (ISNULL(Feb, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     Mar = (ISNULL(new.ModeledCost,0) * (ISNULL(Mar, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     Apr = (ISNULL(new.ModeledCost,0) * (ISNULL(Apr, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     May = (ISNULL(new.ModeledCost,0) * (ISNULL(May, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     Jun = (ISNULL(new.ModeledCost,0) * (ISNULL(Jun, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     Jul = (ISNULL(new.ModeledCost,0) * (ISNULL(Jul, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     Aug = (ISNULL(new.ModeledCost,0) * (ISNULL(Aug, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     Sep = (ISNULL(new.ModeledCost,0) * (ISNULL(Sep, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))) 
     Username = 'Cascade', 
     lastmodified = getdate(), 
     ModeledCost = new.ModeledCost 
from dbo.TBF_BUDGETExpenses as [t] 
left 
join ( select BudgetId, 
        case 
         when not exists (select 1 from dbo.DIMSTD_SCENARIO where SCENARIO0_Name = SCENARIO and SCENARIO2_Name = 'Model') 
         then ISNULL(DriverValue1,0)*ISNULL(DriverValue2,0)*ISNULL(UnitA,0)*ISNULL(UnitB,0)+ISNULL(FixedCost,0) 
         -- normal allocation for all scenarios 
         else (ISNULL(unita,0) * (ISNULL(DriverValue1,0)/ISNULL(NULLIF(DriverValue2,0),1))* ISNULL(UnitB,0))+ISNULL(FixedCost,0) 
          --(ISNULL(unita,0) * (ISNULL(DriverValue1,0)/ISNULL(DriverValue2,0))*ISNULL(UnitB,0))+ISNULL(FixedCost,0) 
          -- allocation for model scenarios 
        end 
      from dbo.TBF_BUDGETExpenses 
     ) as new(BudgetId, ModeledCost) on t.BudgetId = new.BudgetId 
where ISNULL(t.ModeledCost,0) <> 0 

En tant UPDATE:

update t 
set  Oct = (ISNULL(new.ModeledCost,0) * (ISNULL(Oct, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     Nov = (ISNULL(new.ModeledCost,0) * (ISNULL(Nov, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     Dec = (ISNULL(new.ModeledCost,0) * (ISNULL(Dec, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     Jan = (ISNULL(new.ModeledCost,0) * (ISNULL(Jan, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     Feb = (ISNULL(new.ModeledCost,0) * (ISNULL(Feb, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     Mar = (ISNULL(new.ModeledCost,0) * (ISNULL(Mar, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     Apr = (ISNULL(new.ModeledCost,0) * (ISNULL(Apr, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     May = (ISNULL(new.ModeledCost,0) * (ISNULL(May, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     Jun = (ISNULL(new.ModeledCost,0) * (ISNULL(Jun, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     Jul = (ISNULL(new.ModeledCost,0) * (ISNULL(Jul, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     Aug = (ISNULL(new.ModeledCost,0) * (ISNULL(Aug, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))), 
     Sep = (ISNULL(new.ModeledCost,0) * (ISNULL(Sep, 0) /ISNULL(NULLIF(t.ModeledCost,0),1))) 
     Username = 'Cascade', 
     lastmodified = getdate(), 
     ModeledCost = new.ModeledCost 
from dbo.TBF_BUDGETExpenses as [t] 
left 
join ( select BudgetId, 
        case 
         when not exists (select 1 from dbo.DIMSTD_SCENARIO where SCENARIO0_Name = SCENARIO and SCENARIO2_Name = 'Model') 
         then ISNULL(DriverValue1,0)*ISNULL(DriverValue2,0)*ISNULL(UnitA,0)*ISNULL(UnitB,0)+ISNULL(FixedCost,0) 
         -- normal allocation for all scenarios 
         else (ISNULL(unita,0) * (ISNULL(DriverValue1,0)/ISNULL(NULLIF(DriverValue2,0),1))* ISNULL(UnitB,0))+ISNULL(FixedCost,0) 
          --(ISNULL(unita,0) * (ISNULL(DriverValue1,0)/ISNULL(DriverValue2,0))*ISNULL(UnitB,0))+ISNULL(FixedCost,0) 
          -- allocation for model scenarios 
        end 
      from dbo.TBF_BUDGETExpenses 
     ) as new(BudgetId, ModeledCost) on t.BudgetId = new.BudgetId 
where ISNULL(t.ModeledCost,0) <> 0 
Questions connexes