没有明确根节点的 CTE 递归
CTE Recursion without clear root node
我在 SQL 服务器中有一个 table,如下所示:
ID ParentID ChildID
1 465 547
2 547 653
3 653 667
4 902 1005
5 1005 1009
6 1059 1080
注意:ParentID 和 ChildID 指的是另外 table 个人。
我的目标是识别根 parent 并统计 children 的数量。例如,预期的查询输出将是:
ParentID NumChildren
465 3
902 2
1059 1
我看到一些在 CTE 中使用递归的例子,当有一个 parent 的明确标识符时,例如 parentid = null 的条目。但是我的数据不是以这种方式构建的,所以我不知道从哪里开始。
您可以应用一个父项永远不是子项的检查。
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
CTE 中的第一个 select 脚本,用于获取子 ID 中不存在的仅根父 ID 列表
CTE 中 UNION ALL 之后的第二个 select 脚本,要获取层次结构数据,请使用 UNION ALL 和 JOIN 与相同的 CTE 作为父子 ID,父 ID 列为主要 table 即#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;
我在 SQL 服务器中有一个 table,如下所示:
ID ParentID ChildID
1 465 547
2 547 653
3 653 667
4 902 1005
5 1005 1009
6 1059 1080
注意:ParentID 和 ChildID 指的是另外 table 个人。
我的目标是识别根 parent 并统计 children 的数量。例如,预期的查询输出将是:
ParentID NumChildren
465 3
902 2
1059 1
我看到一些在 CTE 中使用递归的例子,当有一个 parent 的明确标识符时,例如 parentid = null 的条目。但是我的数据不是以这种方式构建的,所以我不知道从哪里开始。
您可以应用一个父项永远不是子项的检查。
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
CTE 中的第一个 select 脚本,用于获取子 ID 中不存在的仅根父 ID 列表
CTE 中 UNION ALL 之后的第二个 select 脚本,要获取层次结构数据,请使用 UNION ALL 和 JOIN 与相同的 CTE 作为父子 ID,父 ID 列为主要 table 即#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;