首页 文章

如何加速递归CTE

提问于
浏览
1

鉴于以下递归CTE(我的示例简化了一点):

WITH myCTE (sort, parentid, myid, level, somedata)
AS
(
-- Anchor member definition
    SELECT 
        CAST(ROW_NUMBER() OVER(ORDER BY o.myid) as decimal(38, 20)) as sort,
        o.parentid, 
        o.myid, 
        0 as level, 
        o.somedata
    FROM 
        table1 t1,
        table2 t1,
        datatable o
    WHERE t1.somebool = 1 AND t2.id = t1.foreignid and o.foreignkey = t2.key
        and o.parentid = ''
    UNION ALL
-- Recursive member definition
    SELECT
        CAST(b.sort + (ROW_NUMBER() OVER(ORDER BY o.myid) / power(10.0, b.level + 1)) as decimal(38, 20)) as sort,
        o.parentid, 
        o.myid, 
        b.level + 1, 
        o.somedata
    FROM datatable o
    INNER JOIN myCTE AS b
        ON o.parentid = b.myid

一般的想法如下:从基于table1和table2的项目选择开始,我想启动查询并在锚点中我想要找到没有父项的所有数据,将其与具有主项目的数据连接起来和父母一起挖掘,直到找到所有数据 . 我正在处理一棵未知深度的树,尽管我发现的最高等级是7 .

对递归成员应用额外限制是否有用?我从锚中复制的限制似乎越多越好,但不仅仅过滤“o.parentid = b.myid”就足够了吗?

1 回答

  • 0

    这是我建议的调试/调整方法:

    1)添加以下查询提示以排除存在无限循环的可能性 .

    ...
    )
    SELECT  parentid ,
            myid ,
            [level]
    FROM myCTE 
    OPTION (MAXRECURSION 20)
    

    2)如果返回结果,则尝试使用查询提示注释掉相同的查询 . 它应该在大约相同的时间运行并返回相同数量的结果 .

    3)此时你应该添加排序字段 . 除非有特定的要求将其包含在递归中,否则我建议您将其移至查询CTE,就像这样 .

    ...
    )
    SELECT  parentid ,
            myid ,
            [level],
            -- I'm not sure what this accomplishes:
            -- ROW_NUMBER() OVER (ORDER BY CAST(myid) ASC) / CAST (POWER(10,level) AS DECIMAL(38,20)) AS sort
            -- Wouldn't this look nicer?
            ROW_NUMBER() OVER (ORDER BY [level] ASC, CAST ([parentid] AS INT) ASC, CAST ([myid] AS INT) ASC) AS sort
    
    FROM myCTE 
    ORDER BY [sort]
    OPTION (MAXRECURSION 20)
    

    3)最后,在Table1和Table2上添加回连接 . 我建议你也把它添加到CTE查询中 .

    我意识到你有一个解决方法,但如果你花时间看看我的方法是否适合你,我会很感激 .

相关问题