Baseline Table
ProjectId ProjectName Forecast
--------- ----------- --------
11258 Test Proj1 0.678
11259 Test Proj2 2.57
FundEntity Baseline Table
ProjectId FundEntityId Forecast ForecastDollars
--------- ----------- -------- ---------------
11258 5 0.226
11258 8 0.226
11258 11 0.226
我有一个存储过程循环遍历ProjectSummaryEntity表(Yuck!)中的每个条目,并且对于每个条目,根据FundEntity表中设置的“分配”中断预测。然后,我需要根据“费率”表中的特定费率计算预测的美元金额。费率也由FundEntity决定。
存储过程运行有点慢(6.6k行为14s),由于代码效率低下,我并不感到惊讶。我的问题是,如何在不使用游标的情况下“即时”进行计算?
我使用游标的原因是:
如果我不使用游标,则无法根据预测更新美元。任何帮助表示赞赏。谢谢!
编辑:以上是整个事情的真正简化版本。处理此问题的存储过程位于:http://pastebin.ubuntu.com/629888/
答案 0 :(得分:1)
请注意,存储过程的运行速度不是因为您的光标,而是因为您需要每行运行子查询(11选择+ 1更新)。只需组合其中一些查询,您就可以显着提高性能(例如forHcm,budgetHcm和revPlanHcm的计算可以很容易地连接到一个查询中,因为它们都是基线表列的计算)。
要回答您的特定光标问题,可以删除光标,因为您不需要根据其他行的输出值生成行输出值(例如,如果使用hcmRate值计算一个fundEntityBaselineId的hcmRate值对于另一个FundEntityBaselineId值,则很难避免游标)。 没有光标的最终查询会有点复杂。
将您的存储过程放在http://pastebin.ubuntu.com/629888/并假设如果您使用COALESCE我需要一个OUTER JOIN(没有COALESCE然后INNER JOIN),这是您的单个查询应该是什么样的(修复标记为“refactor”的部分) “我需要更多地了解你的表格:”
SELECT fblId,
ForecastAmount * fundAlloc AS foreHCM
hcmRate,
RE_Value * fundAlloc AS reqForeHcm,
PlanAmount * fundAlloc AS budgetHcm
RevisedPlanAmount * fundAlloc AS revPlanHcm,
actualForHcm_pre * fundAlloc AS actualForeCastHcm
FROM
(SELECT b.FundEntityBaselineId AS fblId,
COALESCE(fa.fundAllocation,100)/100 as fundAlloc,
COALESCE(hcmRate1.Usd_Rate,hcmRate2.HCMRate) as hcmRate,
bl.ForecastAmount,
COALESCE(re.Value,0) as RE_Value,
planHcmRate.BudgetHcmRate as planHcmRate,
bl.PlanAmount,
bl.RevisedPlanAmount,
COALESCE(afp_p.actualForHcm_pre,0) as actualForHcm_pre
FROM FundEntityBaseline b
INNER JOIN ProjectDetail pd ON pd.ProjectId = b.fblProjectId
INNER JOIN Baseline bl on bl.BaselineId = b.BaselineId
INNER JOIN ProjectTeam pt ON bl.ProjectTeamId = pt.ProjectTeamId
INNER JOIN SiteTeam st ON pt.SiteTeamId = st.SiteTeamId
INNER JOIN TeamRole tr ON st.TeamRoleId = tr.RoleId
INNER JOIN Team t ON tr.TeamId = t.TeamId
INNER JOIN FundSource fs on fs.FundSourceId = pd.FundSourceId
INNER JOIN (<* refactor*> SELECT r.BudgetHcmRate
FROM Rate r WHERE r.RateName = (SELECT st.RateName
FROM SiteTeam st INNER JOIN ProjectTeam pt
ON st.SiteTeamId = pt.SiteTeamId
INNER JOIN Baseline bl
ON bl.ProjectTeamId = pt.ProjectTeamId
WHERE bl.BaselineId = fblBaselineId
FETCH FIRST 1 ROW ONLY)
ORDER BY r.EffectiveDate
FETCH FIRST 1 ROW ONLY) as planHcmRate,
LEFT OUTER JOIN (SELECT er.Usd_Rate
FROM FundEntity fe
INNER JOIN EntityCustomerRate er
ON fe.FundAux1 = er.EntityCustomerRateId) AS hcmRate1
ON hcmRate1.FundEntityId = b.FundEntityId AND (fs.FundingType IN ('Direct Bill-Single','Direct Bill-Multiple')) AND t.teamType = 'ITDEVMO'
LEFT OUTER JOIN (<* refactor*> SELECT r.HCMRate
FROM Rate r
INNER JOIN SiteTeam st ON r.RateName = st.RateName
INNER JOIN ProjectTeam pt ON st.SiteTeamId = pt.SiteTeamId
WHERE pt.ProjectTeamId = (SELECT bl.ProjectTeamId
FROM Baseline bl
WHERE bl.BaselineId = b.BaselineId)
ORDER BY r.EffectiveDate DESC
FETCH FIRST 1 ROW ONLY) as hcmRate2 ON (fs.FundingType NOT IN ('Direct Bill-Single','Direct Bill-Multiple') OR t.teamType != 'ITDEVMO')
LEFT OUTER JOIN FundAllocation fa on fa.FundSourceId = pd.FundSourceId AND fa.FundEntityId = b.fblFundEntity
LEFT OUTER JOIN Request re on bl.ProjectMonth = re.ProjectMonth AND bl.ProjectTeamId = re.ProjectTeamId AND re.BaselineType = 'Reforecast'
LEFT OUTER JOIN (<*refactor *>SELECT (((SELECT SUM(bl.ForecastAmount)
FROM Baseline bl
WHERE DATE(SUBSTR(bl.ProjectMonth, 5) || '-' ||
(CASE SUBSTR(bl.ProjectMonth, 1, 3)
WHEN 'Jan' THEN '01'
WHEN 'Feb' THEN '02'
WHEN 'Mar' THEN '03'
WHEN 'Apr' THEN '04'
WHEN 'May' THEN '05'
WHEN 'Jun' THEN '06'
WHEN 'Jul' THEN '07'
WHEN 'Aug' THEN '08'
WHEN 'Sep' THEN '09'
WHEN 'Oct' THEN '10'
WHEN 'Nov' THEN '11'
WHEN 'Dec' THEN '12'
END) || '-01') > DATE((SELECT CurrentMonth FROM Pmo)) AND
bl.ProjectTeamId = (SELECT ProjectTeamId FROM Baseline WHERE BaselineId = fblBaselineId))
+
(SELECT SUM(bl.HcmActualAmount)
FROM Baseline bl
WHERE DATE(SUBSTR(bl.ProjectMonth, 5) || '-' ||
(CASE SUBSTR(bl.ProjectMonth, 1, 3)
WHEN 'Jan' THEN '01'
WHEN 'Feb' THEN '02'
WHEN 'Mar' THEN '03'
WHEN 'Apr' THEN '04'
WHEN 'May' THEN '05'
WHEN 'Jun' THEN '06'
WHEN 'Jul' THEN '07'
WHEN 'Aug' THEN '08'
WHEN 'Sep' THEN '09'
WHEN 'Oct' THEN '10'
WHEN 'Nov' THEN '11'
WHEN 'Dec' THEN '12'
END) || '-01') <= DATE((SELECT CurrentMonth FROM Pmo)) AND
bl.ProjectTeamId = (SELECT ProjectTeamId FROM Baseline WHERE BaselineId = fblBaselineId))) as actualForeHcm_pre) AS afh_p
WHERE ProjectId = projId) as T;
如果这有用,或者您需要更多解释,请告诉我。