T-SQL将Cursor转换为基于SET的操作的问题

时间:2010-11-06 06:30:00

标签: tsql cursor

基本上我有这个光标不是我写的,但是需要一些时间来处理,我想通过一起摆脱光标来尝试改进它。

以下是代码:

DECLARE @class_id int, @title_code varchar(30)

DECLARE title_class CURSOR FOR
SELECT DISTINCT title_code FROM tmp_business_class_titles (NOLOCK)

OPEN title_class

    FETCH title_class INTO @title_code

    WHILE @@FETCH_STATUS = 0
        BEGIN
            SELECT TOP 1 @class_id = bc1.categoryid
            FROM tmp_business_class_titles bct, 
            dbo.Categories bc1 (nolock) 
            join dbo.Categories bc2 (nolock) on bc2.categoryid = bc1.highercategoryid
            join dbo.Categories bc3 (nolock) on bc3.categoryid = bc2.highercategoryid 
            WHERE bc1.categoryid = bct.class_id
                AND title_code = @title_code
            ORDER BY Default_Flag DESC

            UPDATE products 
            SET subcategoryid = @class_id 
            WHERE ccode = @title_code 
                AND spdisplaytype = 'Table'

            UPDATE products
            SET subcategoryid = @class_id
            WHERE highercatalogid IN (
                SELECT catalogid FROM products (nolock)
                WHERE ccode = @title_code AND spdisplaytype = 'Table')

            FETCH title_class INTO @title_code
        END

CLOSE title_class

DEALLOCATE title_class

tmp_business_class_titles 如下所示:

class_id,title_code,Default_flag

7,101WGA,0

7,10315,0

29,8600,0

默认标志始终为0但如果为1则逻辑应自动为该title_id选择默认的class_id。

因此,当前逻辑循环遍历游标中的上表,然后为每个标题选择前1个类id,按默认标志排序(因此应始终首先返回default_flag为1的class_id)。将默认的class_id应用于products表。

此代码需要大约1:20才能运行,我正在尝试将其转换为一个或两个更新语句,但我已经筋疲力尽了。

如果可能的话,任何TSQL Guru都有任何想法,或者我应该重新评估默认标志如何工作的整个逻辑?

欢呼任何帮助。

1 个答案:

答案 0 :(得分:0)

我没有足够的信息可供使用,因此以下查询可能会失败。我特别需要有关产品表的更多信息才能使其正常工作,但假设您拥有SQL Server 2005或更高版本,这可能足以让您开始朝着正确的方向前进。它使用公共表表达式和RANK函数。我强烈建议您了解它们,并且很可能会大大提高查询的效率。

;WITH cteTitle As (
    SELECT 
        sequence = RANK() OVER (PARTITION BY bct.title_code ORDER BY Default_Flag desc)
        ,bct.title_code
        ,bc1.categoryid
    FROM
        tmp_business_class_titles bct
        join Categories bc1 ON bc1.categoryid = bct.class_id
        join Categories bc2 ON bc2.categoryid = bc1.highercategoryid
        join Categories bc3 ON bc3.categoryid = bc2.highercategoryid
 )                            
 UPDATE 
     prod
 SET
     subcategoryid = ISNULL(t.categoryid,t2.categoryid)
 FROM
     products prod
     LEFT join products subprod ON subprod.catalogid = prod.highercatalogid
     LEFT join cteTitle t ON prod.ccode = t.title_code AND t.sequence = 1 AND prod.spdisplaytype = 'Table'
     LEFT join cteTitle t2 ON subprod.ccode = t2.title_code And t2.sequence = 1 AND subprod.spdisplaytype = 'Table'
 WHERE
     t2.categoryid IS NOT NULL