所以我有这个查询按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 :(得分: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
答案 1 :(得分:0)
对于你的情况,肯定设置操作更好,更可行,但我认为最好的方法是不使用任何查询,而是使用表的DDL。创建表时,可以使用持久性创建计算列。就像您的十二个月的列一样,它们可以是计算列,并且所有因素都可以从同一个表中计算出来。这是链接:http://msdn.microsoft.com/en-us/library/ms186241.aspx