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
I have a stored procedure that loops through each entry in the ProjectSummaryEntity Table (Yuck!) and for each one, break the forecast down based on “allocations” set in the FundEntity table. Then, I need to calculate the dollar amount of the forecast based on a certain rate in a “Rate” table. The rate is determined by the FundEntity as well.
The stored procedure is running a bit slow (14s for 6.6k rows) and I’m not surprised due to inefficiency of code. My question is, how do I do “on the fly” calculations without using cursors?
The reason why I use cursors is that:
- forecast amount is broken down first (from ProjectSummary), saved to a variable
- rate is determined, saved to variable
- dollar amount is determined, saved to a variable
- final update statement is run to update forecast and forecast dollars
If I don’t use cursors there’s no way to update the dollars based on the forecast. Any help is appreciated. Thanks!
EDIT: The above is a really simplified version of the whole thing. The stored procedure that deals with this is in: http://pastebin.ubuntu.com/629888/
Note that the Stored Procedure will run slow not because of your cursor, but because of the subqueries you need to run per row (11 selects + 1 update). Just by combining some of those queries you should be able to significantly improve performance (e.g. the calculations for forHcm, budgetHcm and revPlanHcm could easily be joined into one query as they all are calculations on Baseline table columns).
To answer your specific cursor question, it is possible to remove the cursor as you don’t need to generate row output values based on output values for other rows (e.g. if the value of hcmRate for one fundEntityBaselineId was calculated using hcmRate values for another FundEntityBaselineId values, then it would be very difficult to avoid the cursor).
The final query without cursor though will be a little complex.
Taking your stored procedure at http://pastebin.ubuntu.com/629888/ and assuming that if you use COALESCE I need an OUTER JOIN (no COALESCE then INNER JOIN), here is what your single query should look like (to fix the sections marked “refactor” I would need to know more about your tables):
Let me know if this is helpful or you need more explanation.