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
4

2 回答 2

0

如果没有完整的架构、测试数据和预期结果,很难验证这一点。这是您当前更新的基于快速设置的复制。注意:我将您的 ModeledCostCASE向下移动到子查询中,以避免在每个列集中重复它。这取决于你是否合乎逻辑......我假设 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。创建表时,可以使用持久化创建计算列。就像您的十二个月列一样,它们可以是计算列,并且所有参与计算的因素实际上都来自同一个表。这是链接:http: //msdn.microsoft.com/en-us/library/ms186241.aspx

于 2013-03-15T07:26:28.367 回答