在递归CTE下控制兄弟顺序?

时间:2013-08-03 19:22:00

标签: sql-server recursion sql-order-by common-table-expression

我有一个CTE查询,查找主要叶子和子叶子。但我无法控制2个兄弟姐妹之间的叶子选择顺序

表中的每一行都声明为:

(childID INT ,parentID INT ,NAME NVARCHAR(30),location int)

location优先排序IFF,他们是兄弟姐妹。

所以我有这种树结构:这些对具有位置优先级:

enter image description here

例如:

`a` ( location=1) should be before `f` (location=2)
`b` ( location=1) should be before `e` (location=2)
`d` ( location=1) should be **before** `c` (location=2)

问题是我似乎必须首先 order by childID才能看到正确的结构( sibling unsorted )。< / p>

但是 - 我的order by应该是怎样的,这样我才能看到正确的结构(&amp;&amp; sibling sorted )?

(在我的示例中:d应该在c之前)

Here is the working query which yields all the tree leafs ( unsorted siblings)

P.S。 childID 表示有关排序的任何信息。它只是一个占位符。正如我所说,2兄弟之间的位置是location列。(这里,childId被排序,因为这是我插入行的顺序......

2 个答案:

答案 0 :(得分:5)

您可以计算CTE中树节点的路径并将其用于排序

;WITH CTE AS(
   SELECT childID, parentID, 0 AS depth, NAME , location,
         cast(location as varbinary(max)) path
   FROM   @myTable
   WHERE   childID = parentID 
    UNION ALL
    SELECT  TBL.childID, TBL.parentID,
           CTE.depth + 1 , TBL.name ,TBL.location,
           cte.path + cast(TBL.location as binary(4))
    FROM   @myTable AS TBL
            INNER JOIN CTE  ON  TBL.parentID = CTE.childID
    WHERE   TBL.childID<>TBL.parentID
)
SELECT depth, childID, parentID, location, REPLICATE('----', depth) + name
FROM CTE
ORDER BY path

答案 1 :(得分:3)

以下是在Royi Namir的要求下修改i-one的答案,使用左填充数字字符串作为路径:

;WITH CTE AS(
   SELECT childID, parentID, 0 AS depth, NAME , location,
         Cast( Right( '00000' + Cast( Location as VarChar(6) ), 6 ) as  VarChar(1024) ) as Path
   FROM   @myTable
   WHERE   childID = parentID 
    UNION ALL
    SELECT  TBL.childID, TBL.parentID,
           CTE.depth + 1 , TBL.name ,TBL.location,
           Cast( cte.Path + '.' + Right( '00000' + Cast( Tbl.Location as VarChar(6) ), 6 ) as VarChar(1024) )
    FROM   @myTable AS TBL
            INNER JOIN CTE  ON  TBL.parentID = CTE.childID
    WHERE   TBL.childID<>TBL.parentID
)
SELECT depth, childID, parentID, location, REPLICATE('----', depth) + name
FROM CTE
ORDER BY path

注意:未经测试并在度假时写作。

分隔符(.)不是必需的,但可以使结果值更易于阅读,并且可以简化某些操作,例如:找到共同的子路径。