我正在尝试从每个父级获取所有子级计数(子级计数)。
这是示例数据库 (MSSQL)。
INSERT INTO NODES VALUES(NULL, 1);
INSERT INTO NODES VALUES(NULL, 2);
INSERT INTO NODES VALUES(2, 3);
INSERT INTO NODES VALUES(1, 4);
INSERT INTO NODES VALUES(1, 5);
INSERT INTO NODES VALUES(3, 6);
INSERT INTO NODES VALUES(NULL, 7);
INSERT INTO NODES VALUES(NULL, 8);
INSERT INTO NODES VALUES(8, 9);
INSERT INTO NODES VALUES(7, 10);
INSERT INTO NODES VALUES(9, 11);
INSERT INTO NODES VALUES(11, 12);
INSERT INTO NODES VALUES(10, 13);
INSERT INTO NODES VALUES(10, 14);
INSERT INTO NODES VALUES(4, 15);
层次结构在哪里;
- 1
- 4
- 15
- 5
- 2
- 3
- 6
- 7
- 10
- 13
- 14
- 8
- 9
- 11
- 12
期望的结果是:
每次我制定策略来制定查询时,我都会遇到必须在运行时迭代由查询形成的表的情况。
如果我对结果进行深入分组(使用parentid),我可以仅生成子项(而不是子项)的计数,以便我们可以将其加到根。但显然我需要迭代我在查询中形成的表,我不知道递归地说是否正确。
为了更好地表达自己,我会用我已经达到的部分和我想做的事情来展示;
WITH tree AS
(
SELECT n1.parentid, n1.id, 1 AS level
FROM NODES AS n1
WHERE n1.parentid IS NULL
UNION ALL
SELECT n2.parentid, n2.id, level + 1 AS level
FROM NODES AS n2
INNER JOIN tree ON n2.parentid = tree.id
), levels AS
(
SELECT *
FROM tree
)
SELECT parentid, id, (COUNT(*) OVER(PARTITION BY parentid ORDER BY parentid)) AS childrencountofparentid,
ROW_NUMBER() OVER(ORDER BY parentid DESC) AS rownumber
FROM levels
输出是:
我想这样做: Full Image
我想使用前几行的结果,类似于滞后,但我必须迭代所有前几行。
最佳答案
我将使用 Hierarchyid 数据类型来解决这个问题。首先,使用递归 CTE 计算数据集中每一行的值。
with cte as (
select ID, ParentID,
h = cast(concat('/', ID, '/') as varchar(100))
from NODES
where ParentID is null
union all
select child.ID, child.ParentID,
h = cast(concat(Parent.h, child.ID, '/') as varchar(100))
from NODES as child
join cte as Parent
on child.ParentID = Parent.ID
)
select ID, ParentID,
h = cast(h as hierarchyid)
into #t
from cte;
这里唯一“棘手”的事情是我正在构建一个字符串,因为我正在遍历可以转换为hierarchyid数据类型的层次结构。
从那里,很容易计算相当于自连接的子项。
select ID, h.ToString(), count(child.a)
from #t as parent
outer apply (
select a = 1
from #t as child
where child.h.IsDescendantOf(parent.h) = 1
and child.ID <> Parent.ID
) as child
group by parent.ID, h
order by h;
注意 - 我仅在结果集中包含 h 列,以便 a) 显示返回父级的路径,b) 提供排序。如果您不需要这些,则无需包含。需要注意的是,在您想要的结果中,您的子数为 1,因此 13 为 1。我在数据(或您提供的可视化层次结构中)中没有看到 13 有任何子代。我确实看到它有一个 ID 为 14 的同级 - 如果需要计算它,则方法需要稍微改变。
这里需要注意的另一件事 - 如果您可以维护源数据中的 Hierarchyid 列(顺便说一下,这并不难做到),则根本不需要递归 CTE。我喜欢两种方法的混合。也就是说,将 ParentID 的概念保留为列,但在计算中使用 hierarchyid。如果 hierarchyid 被“损坏”(这是可能的,因为它实际上是从基础数据和应用程序逻辑派生的缓存/计算值),则可以根据 ID/ParentID 数据重新计算它。
关于sql - LAG 所有先前行 - 父子数据库查找每个父项的所有子项总数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73220670/