I have a task of reducing the run time of a stored procedure that runs for hours.
Description of task: The cursor takes a set of values @Primary and @Secondary obtained from a query(5000+ rows), finds the @isNewProgram and @NewProgram through the value of @Primary and then operates upon another inbuilt cursor within which the values of each row of the 5000 is compared against some condition and inserted into @tempTable finally. but the individual non parallel processing of each row at a time with cursors is consuming a large time.
I have optimized everything from indexes to usage of common table expressions but how far I try I cannot even start to remove cursors and replace it with set based approach.
SET @CUR_PSD = CURSOR FOR
SELECT DISTINCT B.Primary,Secondary
FROM DetailsTable A
Inner join GroupTable B on B.Primary = A.Primary
WHERE CurrentMonth = @CurrentMonth AND (LEN(Primary) <> 6)
SET @Cur_Billable = CURSOR FOR
SELECT DISTINCT Liability FROM @Liability
OPEN @CUR_PSD
FETCH NEXT FROM @CUR_PSD INTO @Primary,@Secondary
IF @@FETCH_STATUS <> 0
Print 'Error in the Cursor Fetch Statement'
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @IsNewProgram = (SELECT Distinct IsNewProgram
FROM GroupTable WHERE Primary = @Primary)
SELECT @NewProgram = (SELECT Distinct NewProgram
FROM GroupTable WHERE Primary = @Primary)
OPEN @Cur_Billable
FETCH NEXT FROM @Cur_Billable INTO @VarLiability
IF @@FETCH_STATUS <> 0
Print 'Error in the Cursor Fetch Statement'
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO @TempTable
SELECT top 10 Secondary, Primary, GroupName,Liability, DefectCount, DefectCode
FROM (
SELECT Secondary
,@Primary AS Primary
,GroupName
,Liability
,SUM(DefectCount) AS DefectCount,
DefectCode
FROM @PDTopTable
WHERE Liability = @VarLiability
and TPPrimary IN (SELECT Primary FROM GroupTable C
WHERE C.Primary = @Primary)
AND TPNewProgram = CASE WHEN @IsNewProgram = 0
Then @NewProgram
WHEN @IsNewProgram = 2
Then TPNewProgram
ELSE @NewProgram END
AND TPSecondary = @Secondary
GROUP BY Secondary, GroupName, DefectCode,Liability
UNION
SELECT Secondary
,@Primary AS Primary
,GroupName
,Liability
,SUM(DefectCount) AS DefectCount,
DefectCode
FROM @PDBotTable
WHERE Liability = @VarLiability
and TPPrimary IN (SELECT Primary FROM GroupTable C
WHERE C.Primary = @Primary)
AND TPNewProgram = CASE WHEN @IsNewProgram = 0
Then @NewProgram
WHEN @IsNewProgram = 2
Then TPNewProgram
ELSE @NewProgram END
AND TPSecondary = @Secondary
GROUP BY Secondary, GroupName, DefectCode,Liability
) TDG
ORDER BY TDG.Primary, TDG.Secondary,TDG.DefectCount DESC
FETCH NEXT FROM @Cur_Billable INTO @VarLiability
END
CLOSE @Cur_Billable
FETCH NEXT FROM @CUR_PSD INTO @Primary,@Secondary
END
CLOSE @CUR_PSD
I am not looking for someone to do the conversion for me, I just need to know how to get started. I've found a lot of tutorials but I need the right guidance to get started with this as I have never done this before.
Just so you people get to know the outer cursor operates on 5000 rows or more and that condition checking by the outer cursor is what that is making the code run so slow. Should i use inner join on it so that the same desired output can be obtained...?
I mean i want to know what should i do with
With TQ_PlantSupplierDefects(PlantCode,SupplierCode) AS
(
SELECT DISTINCT B.PrimaryCode as PlantCode,SupplierCode
FROM [SMS].[T_SMS_PlantDetailDefects] A
Inner join SMS.T_SMS_PlantGroup B on B.PlantCode = A.PlantCode
WHERE RollingYearMonth = @RollingYearMonth AND (LEN(PrimaryCode) <> 6)
)
If i am going to operate upon the above mentioned CTE and @PDTopTable what should i use. My instinct says i should use combination of functions and joins. Am i right?