【问题标题】:Recursive CTE to find Total for all children parent and depth递归 CTE 以找到所有子级父级和深度的总计
【发布时间】:2021-05-10 02:36:29
【问题描述】:

我希望像这样使用递归 CTE 找到所有 childrencount 和 parentcount 以及 path 和 level 和 currentlevel 的 Total

Id  ParentId    Name    Path        Level   CurrentLevel    ChildrenCount   ParentCount
1   NULL         a      1            4         1               3               0
3   1            c      3,1          3         2               2               1
4   3            d      4,3,1        2         3               1               2
5   4            f      5,4,3,1      1         4               0               3
2   NULL         b      2            5         1               5               0
6   2            g      6,2          4         2               4               1               
7   6            h      7,6,2        3         3               3               2
8   7            i      8,7.6.2      2         4               2               3
9   8            j      9,8,7,6,2    1         5               0               4
10  8            k      10,8,7,6,2   1         5               0               4

我试过下面的代码,但是不知道怎么获取childrencount和parentcount以及path和level和currentlevel,怎么写代码动态计算呢。

CREATE TABLE #temp([id] int, [parentid] int null,[name] varchar(5));

INSERT INTO #temp ([id], [parentid], [name])
VALUES   ('1', null,'a')
       , ('2', null,'b')
       , ('3', '1','c')
       , ('4', '3','d')
       , ('5', '4','e')
       , ('6', '2','f')
       , ('7', '6','h')
       , ('8', '7','i')
       , ('9', '8','j')
       , ('10', '8','k')
WITH AllChildrens as
(
    SELECT p.*, CAST(P.Id AS VarChar(Max)) as [Path]
    FROM Department P where p.ParentId is null

    UNION ALL

    SELECT P1.*, CAST(P1.Id AS VarChar(Max)) + ',' + M.[Path]
    FROM Department P1
    INNER JOIN AllChildrens M
    ON M.Id = P1.ParentId
)
SELECT Id,ParentId,Name,Path From AllChildrens order by Id 

【问题讨论】:

  • 有趣的是,您发布的代码甚至没有通过语法检查。当您为 2 个顶级元素显示 3 和 4 时,“深度”是什么意思?事实上,您希望如何计算所有其余的值?从数据上看并不明显。
  • “祖先”和“后代”可能比“父母”和“孩子”更有意义,尽管如果没有解释就不明显了。为什么CurrentDepth 从来没有1
  • @DaleK depth是层级,表示子项有多少层级。
  • @DaleK 我已经修复了我的数据
  • @HABO 我已经修复了我的数据,感谢您的建议!

标签: sql sql-server tsql recursive-cte


【解决方案1】:

一种选择是使用数据类型hierarchyid

示例

;with cteP as (
      Select ID
            ,parentid 
            ,Name 
            ,HierID = convert(hierarchyid,concat('/',ID,'/'))
      From   #Temp 
      Where  parentid is null
      Union  All
      Select ID  = r.ID
            ,parentid  = r.parentid 
            ,Name   = r.Name
            ,HierID = convert(hierarchyid,concat(p.HierID.ToString(),r.ID,'/'))
      From   #Temp r
      Join   cteP p on r.parentid  = p.ID)
Select ID
      ,parentid
      ,Name 
      ,Path      = HierID.ToString()
      ,Depth     = ( Select max(HierID.GetLevel() ) from cteP where HierID.ToString() like A.HierID.ToString()+'%') - HierID.GetLevel()
      ,Lvl       = HierID.GetLevel()
      ,ChildCnt  = ( Select count(*) from cteP where HierID.ToString() like A.HierID.ToString()+'%') -1
      ,ParentCnt = len(HierID.ToString()) - len(replace(HierID.ToString(),'/','')) - 2
 From cteP A
 Order By A.HierID

结果

【讨论】:

  • 太棒了!! PS ParentAccount 与期望的结果不匹配 - 但也许 OP 是错误的?
  • 为什么 id=5 row depth=0 但 lvl=4 应该是 depth=1 ?
  • @beiduoan 如果您希望它基于 1 而不是基于 0,只需添加一个...
  • @beiduoan 你做了几处修改,我决定你可以在确定最终结果时进行调整。
  • @JohnCappelletti 我已经确认了我的结果,您可以调整最新的代码。谢谢
猜你喜欢
  • 2019-05-11
  • 1970-01-01
  • 2018-03-30
  • 1970-01-01
  • 1970-01-01
  • 2013-09-15
  • 2012-11-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多