So I have this stored procedure (in Microsoft SQL Server) which is kinda slow.
CREATE PROCEDURE [APInvoice].[GetDuplicateInvoicesList]
(
@VendorID NVARCHAR(15),
@InvoiceNumber NVARCHAR(50),
@IncidentNumber NVARCHAR(50)
)
AS
BEGIN
DECLARE @_InvoiceID INT
DECLARE @_InvoiceNumber NVARCHAR(50)
DECLARE @_InvoiceAmount DECIMAL(13,2)
DECLARE @_InvoiceDate DATE
DECLARE @_InitiationDateTime DATE
DECLARE @_IncidentStatus NVARCHAR(50)
DECLARE @_VendorID NVARCHAR(15)
DECLARE @_InvoiceNumberCount INT
DECLARE @LOCAL_TABLEVARIABLE TABLE
(
InvoiceNumber NVARCHAR(50),
InitiationDateTime DATE,
VendorID NVARCHAR(15),
rn int --row number
)
DECLARE @LOCAL_TABLEVARIABLE_2 TABLE
(
InvoiceID INT,
InvoiceNumber NVARCHAR(50),
InvoiceAmount DECIMAL(13,2),
InvoiceDate DATE,
InitiationDateTime DATE,
IncidentStatus NVARCHAR(50),
VendorID NVARCHAR(15),
TheOldestInvoiceIndex INT,
ProcessName NVARCHAR(100)
)
DECLARE @InvoiceNumberCheckedArray TABLE
(
InvoiceNumber NVARCHAR(50)
)
DECLARE @StepTable TABLE
(
IncidentID INT,
IncidentNumber2 INT,
StepName NVARCHAR(50),
ProcessName2 NVARCHAR(100)
)
-- Get a list of all current statuses (with stepnames) for all incidents
INSERT INTO @StepTable
SELECT iin.id as IncidentID, st.IncidentNumber as IncidentNumber2, st.StepName as StepName, st.ProcessName as ProcessName2
FROM APInvoice.vwAPInvoiceActiveUltimusTasks st
INNER JOIN APInvoice.InvoiceIncidentData iin ON iin.ProcessName = st.ProcessName AND iin.IncidentNumber = st.IncidentNumber;
-- Get a list of all InvoiceNumbers that are open for given VendorID
INSERT INTO @LOCAL_TABLEVARIABLE
SELECT * FROM (
SELECT
InvoiceNumber
,InitiationDateTime
,VendorID
,ROW_NUMBER() OVER(PARTITION BY InvoiceNumber ORDER BY InitiationDateTime DESC) AS rn
FROM APInvoice.InvoiceIncidentData
WHERE VendorID = @VendorID
AND IncidentNumber <> @IncidentNumber
AND (IncidentStatus = 'Approved' OR (IncidentStatus = 'Pending'))
) result
WHERE rn = 1
DECLARE LocalCursor CURSOR FOR
-- Find all duplicates + max 10 non-duplicate invoices
SELECT InvoiceNumber FROM @LOCAL_TABLEVARIABLE ORDER BY InitiationDateTime DESC
OPEN LocalCursor
FETCH NEXT FROM LocalCursor INTO @_InvoiceNumber
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN
SET @_InvoiceNumberCount = (SELECT COUNT(*) FROM @LOCAL_TABLEVARIABLE_2 WHERE InvoiceNumber = @_InvoiceNumber)
IF @_InvoiceNumberCount = 0
BEGIN
INSERT INTO @LOCAL_TABLEVARIABLE_2
SELECT
id AS InvoiceID,
InvoiceNumber,
InvoiceAmount,
InvoiceDate,
InitiationDateTime,
IncidentStatus,
VendorID,
ROW_NUMBER() OVER(ORDER BY InvoiceNumber ASC) AS TheOldestInvoiceIndex, -- the first is the oldest and original, others are duplicates
REPLACE(ProcessName, 'Invoice_Approval_', '') AS ProcessName
FROM APInvoice.InvoiceIncidentData
WHERE VendorID = @VendorID
AND InvoiceNumber = @InvoiceNumber
AND IncidentNumber <> @IncidentNumber
AND (IncidentStatus = 'Approved' OR (IncidentStatus = 'Pending'))
ORDER BY InitiationDateTime ASC
INSERT INTO @InvoiceNumberCheckedArray
SELECT @_InvoiceNumber AS InvoiceNumber
END
END
FETCH NEXT FROM LocalCursor INTO @_InvoiceNumber
END
CLOSE LocalCursor
DEALLOCATE LocalCursor
SELECT lt.InvoiceID, lt.InvoiceNumber, lt.InvoiceAmount, lt.InvoiceDate, lt.IncidentStatus, lt.TheOldestInvoiceIndex, lt.ProcessName, s.StepName
FROM @LOCAL_TABLEVARIABLE_2 lt
INNER JOIN @StepTable s ON s.IncidentID = lt.InvoiceID
ORDER BY InvoiceNumber DESC;
END
I would really appreciate it if someone showed me a way to optimize this procedure.