当前位置: 首页 > 面试题库 >

sql父子树的排序顺序

西门嘉澍
2023-03-14
问题内容

假设这张table

ParentId    ChildId    SortOrder
---------------------------------
0           1          0
1           2          1
2           3          1
2           4          2
2           6          3
1           7          2
1           9          3
9           10         1
9           12         2

我将如何编写简单的CTE(或其他类型的查询),以在任何级别返回它们的父/子关系,但将所有子项的排序顺序保持在父项之下。

基本上,这将是一个简单的树视图,其中的子项目按特定的排序顺序进行排序。

SQL Server 2008是数据库

更新:可以有无限个父级/子级-我尝试了其他堆栈问题/答案中的一些示例,但没有一个在子级中包含排序顺序。

示例结果应为:

parent (sort 0)
    child (sort 1)
    child (sort 2)
    child (sort 3)
        child-child (sort 1)
    child (sort 4)
        child-child (sort 1)
        child-child (sort 2)

等等。

希望这是有道理的-也许我正在看这个错误,这样的结果最好在中间层构建?

无论如何,任何反馈都将不胜感激


问题答案:

具有特殊排序覆盖的递归CTE。请注意2的子级中的排序覆盖(我对源表进行了少许修改以测试此功能)

declare @relations table(ParentID int, ChildID int, SortOrder int, treeID int);

insert into @relations values
(0,1,0,0), (1,2,1,0), (2,3,2,0), (2,4,1,0), (2,6,3,0), (1,7,2,0), (1,9,3,0), (9,10,1,0), (9,12,2,0) --tree 0
, (0,1,0,1), (1,2,1,1), (2,3,2,1), (2,4,1,1), (2,6,3,1), (1,7,2,1), (1,9,3,1), (9,10,1,1), (9,12,2,1) --tree 1

; with cte(ParentId,ChildId,SortOrder,depth,agg,treeID) as (
    select null,ParentId,SortOrder,0
    , right('0000000'+CAST(treeID as varchar(max)),7)
        +right('0000000'+CAST(SortOrder as varchar(max)),7)
    , treeID
    from @relations where ParentId=0
    union all
    select cte.ChildId,r.ChildId,r.SortOrder,cte.depth+1
    , cte.agg
        +right('0000000'+CAST(r.treeID as varchar(max)),7)
        +right('0000000'+CAST(r.SortOrder as varchar(max)),7)
        +right('0000000'+CAST(r.ChildId as varchar(max)),7)
    , r.treeID
    from cte
    inner join @relations r on r.ParentID=cte.ChildId
    where cte.depth<32767
    and r.treeID=cte.treeID
)
select
tree=case depth when 1 then cast(ParentID as varchar(30))+' (sort '+cast(SortOrder as varchar(30))+')'
    else REPLICATE(CHAR(9),depth-1)
        + cast(ChildId as varchar(30))+' (sort '+cast(SortOrder as varchar(30))+')'
    end
from cte
where depth>0
order by agg
option (maxrecursion 32767);

结果:

tree
--------------------------------------------------
0 (sort 0)
    2 (sort 1)
        4 (sort 1)
        3 (sort 2)
        6 (sort 3)
    7 (sort 2)
    9 (sort 3)
        10 (sort 1)
        12 (sort 2)
0 (sort 0)
    2 (sort 1)
        4 (sort 1)
        3 (sort 2)
        6 (sort 3)
    7 (sort 2)
    9 (sort 3)
        10 (sort 1)
        12 (sort 2)


 类似资料:
  • 问题内容: 我正在尝试创建一个论坛设置,您可以在其中对特定帖子发表评论,并将回复按日期顺序显示在父项的正下方。父级下面只有一个子级别。这是示例数据集: 这就是我想要最终得到的: 我知道我需要某种CTE,但这不会在适当的父项下对子项进行排序(显然,因为没有ORDER BY子句);我不知道正确的顺序。谁能提供一些见识? 问题答案: 对于单个级别的深度,您无需使用递归-尝试:

  • 问题内容: 我想知道是否有按IN()子句中的值顺序进行排序的方法(可能是一种更好的方法)。 问题是我有2个查询,一个查询获取所有ID,第二个查询获取所有信息。第一个创建我要第二个排序的ID的顺序。这些ID以正确的顺序放入IN()子句中。 因此,它类似于(极其简化): 问题在于第二个查询不会以将ID放入IN()子句中的顺序来返回结果。 我发现的一种解决方案是将所有ID放入具有自动递增字段的临时表中,

  • 问题内容: 我们有一个带有父子关系的表,希望对它进行排序。排序标准是这样的,以便在遍历结果时,与父ID匹配的行应该已经存在: 问题在于两个密钥都是字符串,因此按ID或PARENT_ID排序将无法解决问题。 问题答案: 对于Oracle,使用分层查询:

  • 问题内容: 我想知道是否有按IN()子句中的值顺序进行排序的方法(可能是一种更好的方法)。 问题是我有2个查询,一个查询获取所有ID,第二个查询获取所有信息。第一个创建我要第二个排序的ID的顺序。这些ID以正确的顺序放入IN()子句中。 因此,它类似于(极其简化): 问题在于第二个查询不会以将ID放入IN()子句中的顺序来返回结果。 我发现的一种解决方案是将所有ID放入具有自动递增字段的临时表中,

  • 问题内容: 我有以下查询,该查询基于逗号分隔的列表返回行 我希望此查询的结果以ID在列表中的顺序返回。SQL可以做到吗? 提前致谢 问题答案: 如果您需要输出以特定顺序显示,则需要使用服务器可以排序的内容来指定该顺序。不知道您要使用哪个引擎,一般的方案是创建一个临时表或使用行集构造函数将每个记录ID与所需的排序顺序配对。 例如(SQL Server)

  • 问题内容: 像这样对表格进行排序的最佳方法是什么: 要通过分级排序,它 的ID 或 名字 : “比萨饼” //节点1 “piperoni” //节点1.1 “奶酪” //节点1.2 “额外的奶酪” //节点1.2.1 “vegetariana” //节点1.3 “汉堡” //节点2 ‘咖啡’//节点3 编辑: 名称 末尾的数字是为了更好地可视化strucutre,而不是用于排序。 编辑2: 正如多