按递归深度有限的前任排序

Sort by predecessor with limited recursion depths

我有一个这样的链表

 LineID      PredecessorLineID SuccessorLineID 
 ----------- ----------------- --------------- 
 3           NULL              2               
 2           3                 815             
 815         2                 1               
 1           815               195             
 195         1                 52      

我需要按照没有前导的行排在第一位的方式排序,然后是第一行作为前导的行,依此类推

我可以用这个查询对其进行排序

 WITH    q ([LineID], PredecessorLineID,  SuccessorLineID, init, lvl) AS
                        (
                            SELECT  [LineID], [PredecessorLineID],  [SuccessorLineID], [LineID], 1
                            FROM    Lines
                            WHERE   [PredecessorLineID] is null 

                            UNION ALL

                            SELECT   mt.[LineID], mt.[PredecessorLineID],  mt.[SuccessorLineID], q.init, q.lvl + 1
                            FROM    q
                            JOIN    Lines mt
                            ON      mt.[LineID] = q.SuccessorLineID                                 

                            )

    select  * from  q Option ( maxrecursion 4  ) 

这给出了正确的结果,但问题在于递归深度。它真的是 n - 1。我有几千行,需要将 maxrecursion 设置为非常高的值。

这个查询需要在一个视图中,这就是为什么我什至不能设置 maxrecursion 并且需要将它设置为服务器的默认值。

有没有一种方法可以减少递归?

我不建议在 SQL 数据库中以这种方式存储链表。它们处理起来相当麻烦。我的意思是,层次结构很好,但它们的深度通常不超过 100。并且 "one-off" 递归 CTE 可以无限递归。

也就是说,您可能有一个有效的用例。您可以创建一个 UDF 并设置递归:

create function udf_get_hierarchy ()
returns @q as table (
    . . .  -- column definitions go here
)
BEGIN
    WITH q ([LineID], PredecessorLineID,  SuccessorLineID, init, lvl) AS (
          SELECT  [LineID], [PredecessorLineID],  [SuccessorLineID], [LineID], 1
          FROM Lines
          WHERE [PredecessorLineID] is null 
          UNION ALL
          SELECT mt.[LineID], mt.[PredecessorLineID],  mt.[SuccessorLineID], q.init, q.lvl + 1
          FROM q JOIN
               Lines mt
               ON mt.[LineID] = q.SuccessorLineID                                 
        )
    SELECT * 
    INTO @q
    FROM q
    OPTION ( MAXRECURSION 0 );
END;

如果您正在创建一个函数,您可能希望将一个参数传递给它,以获取特定 ID 的层次结构。