【问题标题】:CTE Recursion without clear root node没有清除根节点的 CTE 递归
【发布时间】:2020-01-07 21:49:14
【问题描述】:

我在 SQL Server 中有一个如下所示的表:

ID  ParentID    ChildID
1   465         547
2   547         653
3   653         667
4   902         1005
5   1005        1009
6   1059        1080

注意:ParentID 和 ChildID 指的是另一张人员表。

我的目标是确定根父母并计算孩子的数量。例如,预期的查询输出将是:

ParentID    NumChildren
465         3
902         2
1059        1 

我见过一些在 CTE 中使用递归的例子,当有一个明确的父标识符时,例如 parentid = null 的条目。但是我的数据不是以这种方式构建的,所以我不知道从哪里开始。

【问题讨论】:

    标签: sql-server common-table-expression


    【解决方案1】:

    您可以检查父母永远不是孩子。

    with cte as (
    select  ParentID, ChildID  
      from TABLE  
    where parentid not in (select childid from TABLE ) -- the parent is never a child
    
      union all
    
      select  parent.ParentID, child.ChildID
      from TABLE child
      inner join cte parent
      on child.parentid =parent.ChildID
    )
    select ParentID,count(*) as NumChildren
    from cte
    group by ParentID
    

    【讨论】:

      【解决方案2】:

      首先在 CTE 中选择脚本,只获取 Child ID 中不存在的 Root Parent ID 列表

      在 CTE 中 UNION ALL 之后的第二个选择脚本,要获取层次结构数据,使用具有相同 CTE 的 UNION ALL 和 JOIN 作为主表的父 ID 列的父子 ID,即#tblA

      您需要使用聚合函数 COUNT() 来根据父 ID 获取子计数 您需要使用 GROUP BY 子句才能使用聚合函数 COUNT()

      请检查以下脚本以获得您的预期结果。

      SELECT
          A.*
          INTO #tblA
      FROM
      (
          SELECT 1 ID,465 ParentID,547 ChildID UNION ALL
          SELECT 2,547,653 UNION ALL
          SELECT 3,653,667 UNION ALL
          SELECT 4,902,1005 UNION ALL
          SELECT 5,1005,1009 UNION ALL
          SELECT 6,1059,1080
      ) A
      
      ;WITH CTE_REC
      AS
      (
          --Get Only Root Parent ID list which are not exists in Child ID
          SELECT
              A.ParentID,A.ChildID
          FROM #tblA A
          WHERE NOT EXISTS
          (
              SELECT
                  1
              FROM #tblA c
              WHERE c.ChildID = A.ParentID
          )
          --to get Heirarchy data, use UNION ALL and JOIN with same CTE as a parent Child ID with Parent ID column of main table
          UNION ALL
          SELECT
              CR.ParentID,ta.ChildID
          FROM CTE_REC CR
          INNER JOIN #tblA ta ON ta.ParentID = CR.ChildID
      )
      SELECT
          c.ParentID,
          COUNT(c.ChildID) AS NumChildren --Use aggregate function count() to get child count against parent id
      FROM CTE_REC c
      GROUP BY c.ParentID; -- Use Group By Clause to use aggregate function count()
      
      DROP TABLE #tblA;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-04-14
        • 2010-10-24
        • 2011-10-02
        • 1970-01-01
        • 2022-07-08
        • 1970-01-01
        • 2021-05-22
        • 1970-01-01
        相关资源
        最近更新 更多