user9912287
user9912287

Reputation:

How to optimize the Cursor to the Set based operator query?

I had cursor in my stored procedure. I have updated to while loop to execute faster. But my while loops takes same long time. Please help me to debug my script. Please find my below code.

I need the help in updating Cursor to set based operator Query in MS SQL.

DECLARE @orderArray INT
    ,@LeftTSMKEY NVARCHAR(250)
    ,@ListElid NVARCHAR(250)
    ,@ListType NVARCHAR(250)
    ,@ListType_Prev NVARCHAR(250)

SET @ListType_Prev = ''
SET @inc = 0

DECLARE cursql CURSOR
FOR
SELECT ListElid
    ,ListType
    ,orderArray
    ,LeftTSMKEY
FROM QAT_ListElid
ORDER BY ListType
    ,orderArray

OPEN cursql

FETCH NEXT
FROM cursql
INTO @ListElid
    ,@ListType
    ,@orderArray
    ,@LeftTSMKEY

WHILE (@@Fetch_status = 0)
BEGIN
    IF @ListType <> @ListType_Prev
    BEGIN
        SET @inc = 0
        SET @ListType_Prev = @ListType
    END
    ELSE IF @ListType = @ListType_Prev
    BEGIN
        SET @inc = @inc + 1
    END

    IF @inc <> @orderArray
    BEGIN
        INSERT [QAT_ListElid2] (
            [ListElid]
            ,[ListType]
            ,[orderArray]
            ,[LeftTSMKEY]
            )
        VALUES (
            @ListElid
            ,@ListType
            ,@inc
            ,@LeftTSMKEY + CAST(@inc AS NVARCHAR(10)) + ']'
            )
    END

    FETCH NEXT
    FROM cursql
    INTO @ListElid
        ,@ListType
        ,@orderArray
        ,@LeftTSMKEY
END

CLOSE cursql

DEALLOCATE cursql

Please find below sample data

enter image description here

ListElid    ListType    orderArray  LeftTSMKEY
1000:odl5:7pt_ToxAcuDo[0]   1000:odl5:7pt_ToxAcuDo  0   ToxAcuDo[
106i:odl5:7pt_ToxAcuDo[0]   106i:odl5:7pt_ToxAcuDo  0   ToxAcuDo[
107:107:7pt_NIL[0]  107:107:7pt_NIL 0   NIL[
107:1827:7pt_NIL[0] 107:1827:7pt_NIL    0   NIL[
107:1827:7pt_NIL[1] 107:1827:7pt_NIL    1   NIL[
107:1827:7pt_NIL[3] 107:1827:7pt_NIL    3   NIL[
107:1hqn:7pt_NIL[0] 107:1hqn:7pt_NIL    0   NIL[
107:1hqn:7pt_NIL[1] 107:1hqn:7pt_NIL    1   NIL[
107:1rj7:7pt_NIL[0] 107:1rj7:7pt_NIL    0   NIL[
107:1rj7:7pt_NIL[1] 107:1rj7:7pt_NIL    1   NIL[
107:1rsg:7pt_NIL[0] 107:1rsg:7pt_NIL    0   NIL[
107:1s2r:7pt_NIL[0] 107:1s2r:7pt_NIL    0   NIL[
107:1s2r:7pt_NIL[1] 107:1s2r:7pt_NIL    1   NIL[
107:1s2r:7pt_NIL[2] 107:1s2r:7pt_NIL    2   NIL[
107:1s2r:7pt_NIL[4] 107:1s2r:7pt_NIL    4   NIL[
107:1vf:7pt_ NIL[0] 107:1vf:7pt_NIL    0    NIL[

Upvotes: 0

Views: 179

Answers (2)

Zhorov
Zhorov

Reputation: 29943

If I understand the question correctly, the next statement is a possible solution.

Tables:

CREATE TABLE QAT_ListElid (
    ListElid nvarchar(250),  
    ListType nvarchar(250), 
    orderArray int, 
    LeftTSMKEY nvarchar(250)
)
INSERT INTO QAT_ListElid
    (ListElid, ListType, orderArray, LeftTSMKEY)
VALUES
    ('1000:odl5:7pt_ToxAcuDo[0]',   '1000:odl5:7pt_ToxAcuDo',   0, 'ToxAcuDo['),
    ('106i:odl5:7pt_ToxAcuDo[0]',   '106i:odl5:7pt_ToxAcuDo',   0, 'ToxAcuDo['),
    ('107:107:7pt_NIL[0]',          '107:107:7pt_NIL',          0, 'NIL['),
    ('107:1827:7pt_NIL[0]',         '107:1827:7pt_NIL',         0, 'NIL['),         -- 107:1827:7pt_NIL
    ('107:1827:7pt_NIL[1]',         '107:1827:7pt_NIL',         1, 'NIL['),         -- 107:1827:7pt_NIL
    ('107:1827:7pt_NIL[3]',         '107:1827:7pt_NIL',         3, 'NIL['),         -- 107:1827:7pt_NIL
    ('107:1hqn:7pt_NIL[0]',         '107:1hqn:7pt_NIL',         0, 'NIL['),
    ('107:1hqn:7pt_NIL[1]',         '107:1hqn:7pt_NIL',         1, 'NIL['),
    ('107:1rj7:7pt_NIL[0]',         '107:1rj7:7pt_NIL',         0, 'NIL['),
    ('107:1rj7:7pt_NIL[1]',         '107:1rj7:7pt_NIL',         1, 'NIL['),
    ('107:1rsg:7pt_NIL[0]',         '107:1rsg:7pt_NIL',         0, 'NIL['),
    ('107:1s2r:7pt_NIL[0]',         '107:1s2r:7pt_NIL',         0, 'NIL['),         -- 107:1s2r:7pt_NIL
    ('107:1s2r:7pt_NIL[1]',         '107:1s2r:7pt_NIL',         1, 'NIL['),         -- 107:1s2r:7pt_NIL
    ('107:1s2r:7pt_NIL[2]',         '107:1s2r:7pt_NIL',         2, 'NIL['),         -- 107:1s2r:7pt_NIL
    ('107:1s2r:7pt_NIL[4]',         '107:1s2r:7pt_NIL',         4, 'NIL['),         -- 107:1s2r:7pt_NIL
    ('107:1vf:7pt_ NIL[0]',         '107:1vf:7pt_NIL',          0, 'NIL[')
CREATE TABLE QAT_ListElid2 (
    ListElid nvarchar(250),  
    ListType nvarchar(250), 
    orderArray int, 
    LeftTSMKEY nvarchar(250)
)

Statement:

;WITH ChangesCTE AS (
    SELECT 
        ListElid, ListType, orderArray, LeftTSMKEY,
        CASE 
            WHEN ListType = LAG(ListType) OVER (PARTITION BY ListType ORDER BY orderArray) THEN 1 
            ELSE 0
        END AS [Change]
    FROM QAT_ListElid
), FinalCTE AS (
    SELECT 
        ListElid, ListType, orderArray, LeftTSMKEY,
        SUM([Change]) OVER (PARTITION BY ListType ORDER BY ListType, orderArray) AS [inc]
    FROM ChangesCTE
)
INSERT INTO QAT_ListElid2
    ([ListElid], [ListType], [orderArray], [LeftTSMKEY])
SELECT 
    ListElid, 
    ListType, 
    [inc] AS orderArray, 
    LeftTSMKEY + CAST([inc] as nvarchar(10)) + ']' AS LeftTSMKEY
FROM FinalCTE
WHERE orderArray <> [inc]

or anotehr statement as second option:

INSERT INTO QAT_ListElid2
    ([ListElid], [ListType], [orderArray], [LeftTSMKEY])
SELECT 
    ListElid, 
    ListType, 
    [inc] AS orderArray, 
    LeftTSMKEY + CAST([inc] as nvarchar(10)) + ']' AS LeftTSMKEY
FROM (
    SELECT 
        ListElid, ListType, orderArray, LeftTSMKEY,
        ROW_NUMBER() OVER (PARTITION BY ListType ORDER BY orderArray) - 1 AS [Inc]
    FROM QAT_ListElid
) t
WHERE orderArray <> [inc]

Result (two inserted rows):

--------------------------------------------------------------
ListElid            ListType            orderArray  LeftTSMKEY
--------------------------------------------------------------
107:1827:7pt_NIL[3] 107:1827:7pt_NIL    2           NIL[2]
107:1s2r:7pt_NIL[4] 107:1s2r:7pt_NIL    3           NIL[3]

Upvotes: 0

Raghuveer
Raghuveer

Reputation: 9

They are based on the DECLARE CURSOR syntax and are used mainly in Transact-SQL scripts, stored procedures and triggers. Transact-SQL cursors are implemented on the server and are managed by Transact-SQL statements sent from the client to the server. They may also be contained in batches, stored procedures, or triggers.

Like INT, VARCHAR and other data types, Cursors are declared in T-SQL batches. SQL Server comes with associated instructions to manage it:

  1. OPEN to tell SQL Server to run the query and populate cursor with results set;

  2. CLOSE to tell SQL Server to release resources used by cursor;

  3. FETCH to tell SQL Server to retrieve a specific row from cursor. When we use this function, we can get the outcome of FETCH instruction in @@FETCH_STATUS variable. If it’s set to 0, this means that the instruction succeeded.

Upvotes: 0

Related Questions