1

したがって、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
4

2 に答える 2

0

完全なスキーマ、テストデータ、および期待される結果がなければ、これを検証するのは困難です。これは、現在のアップデートのクイックセットベースの再現です。CASE注:各列セットで繰り返されないようにするために、ModeledCostをサブクエリに移動しました。それが論理的に理にかなっているかどうかはあなた次第です...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
于 2013-03-14T19:13:19.803 に答える
0

あなたの場合、間違いなく設定操作の方が優れていて実行可能ですが、私が考える最善のアプローチは、クエリを使用せず、テーブルの DDL を使用することです。テーブルを作成するときに、永続化された計算列を作成できます。12 か月の列と同様に、それらは計算列にすることができ、実際にはすべての要素が同じテーブルから計算に関与します。リンクは次のとおりです。 http://msdn.microsoft.com/en-us/library/ms186241.aspx

于 2013-03-15T07:26:28.367 に答える