2013-03-14 30 views
1

因此,我有這個查詢通過id搜索id並相應地計算成本。但速度很慢,我想了解如何將其轉換爲基於集合的操作。將光標轉換爲基於集合的操作

因此,根據我們的情況,我們計算不同的建模成本。

當用戶更新驅動程序時,我們可以根據其更改的位置在整個驅動程序列上運行更新。

但是,當涉及到計算模型的成本。 由於固定成本不同,所以一行一行地做,然後除以幾個月。我已經粘貼下面的代碼。通過基於集合的操作還有一種方法嗎?

首先,我們更新取決於同桌的驅動程序使用更新已經改變了什麼樣的價值,然後更新按行建模成本行(這是很慢)

代碼:

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 

回答

0

對於你的情況下,絕對設置操作是更好的,可行的,但我認爲最好的方法不是使用任何查詢,而是使用表的DDL。在創建表格時,您可以使用持久創建計算列。就像你的十二個月的專欄一樣,它們可以是計算列,所有的因素都可以從同一張表中計算出來。這裏是鏈接:http://msdn.microsoft.com/en-us/library/ms186241.aspx

0

如果沒有完整的模式,測試數據和預期結果,很難驗證它。這是基於當前更新的快速設置。注意:我將您的ModeledCost CASE下移到子查詢中,以避免在每個列集中重複它。直到你是否符合邏輯意義......我認爲BudgetId是PK。

運行升級爲SELECT確認其生產所需的結果集:

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 

作爲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 
相關問題