Sql server 在递归CTE下控制同级顺序?

Sql server 在递归CTE下控制同级顺序?,sql-server,recursion,sql-order-by,common-table-expression,Sql Server,Recursion,Sql Order By,Common Table Expression,我有一个CTE查询,它查找主叶和子叶。但是我在控制两个兄弟姐妹之间的叶子选择顺序时遇到了问题: 表中的每一行声明为: childID INT,parentID INT,NAME NVARCHAR30,location INT 如果位置是排序的优先项,则它们是同级 所以我有一个树状结构:这些对具有位置优先级: 例如: `a` ( location=1) should be before `f` (location=2) `b` ( location=1) should be before `e`

我有一个CTE查询,它查找主叶和子叶。但是我在控制两个兄弟姐妹之间的叶子选择顺序时遇到了问题:

表中的每一行声明为:

childID INT,parentID INT,NAME NVARCHAR30,location INT

如果位置是排序的优先项,则它们是同级

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

例如:

`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)
问题是,似乎我必须首先按childID排序,才能看到未排序的正确结构兄弟

但是-我的order by应该是什么样子的,这样我才能看到正确的结构和兄弟姐妹排序

在我的例子中:d应该在c之前


p、 s.childID没有表示任何有关排序的信息。它只是一个占位符。正如我所说,两兄弟之间的位置是通过location列确定的。在这里,childId被排序,因为这是我插入行的顺序…

您可以计算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

应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
注:未经测试,是在度假时写的


分离器。不需要,但会使结果值更易于读取,并可能简化某些操作,例如查找公共子路径。

这些技巧等让我觉得非常愚蠢。:-但我很高兴学习这项技术。-附言。它正在发挥作用。通常情况下,该位置用零填充,以确保每个级别的宽度是固定的,例如,右“00000”+铸造Tbl。位置为VarChar6,6。这避免了按字母顺序排列数字时出现的任何奇怪现象。@HABO,对,谢谢,更正了,但我使用了一些不同的方法,它们保留了相同的逻辑,但有点短visually@RoyiNamir,HABO做了重要通知,请查看更新的答案,这样您就不会得到示例1、10、2、20、3、4、5。。当兄弟姐妹的数量足够大时。@i-one我不明白你的第一个解决方案的问题,这对我来说很好,请解释一下Hanks!祝你假期愉快!你能看看我的相关问题吗?@RoyiNamir-显然不是。由作者自愿删除。抱歉,我认为它更适合DB站点,所以我将其移动:-感谢您的努力。@downvoter,Downvoting没有对如此详细的问题进行评论或解释-这不是本站点的精神-报道。