如何计算树形结构中子树的节点权重总和?
计算树形结构中子树的权重总和
表结构
create table Tree( id Int primary key, pid Int REFERENCES Tree(id), weight Int)
现有数据
| id | pid | weight |
|---|---|---|
| 4 | null | 3 |
| 1 | 4 | 1 |
| 5 | 4 | 1 |
| 6 | 4 | 1 |
| 2 | 1 | 1 |
| 3 | 1 | 1 |
| 7 | 3 | 2 |
| 8 | 3 | 1 |
期望结果
| id | pid | sum |
|---|---|---|
| 4 | null | 14 |
| 1 | 4 | 9 |
| 5 | 4 | 1 |
| 6 | 4 | 1 |
| 2 | 1 | 1 |
| 3 | 1 | 4 |
| 7 | 3 | 2 |
| 8 | 3 | 1 |
解决方案:使用递归CTE
递归CTE是处理树形结构的标准方案,主流数据库(MySQL 8+、PostgreSQL、SQL Server等)都支持。下面提供两种直观的实现方式:
方式1:从根节点遍历所有子节点后求和
这种方法通过递归记录每个节点的所有子节点,再按根节点分组计算总权重,逻辑清晰易懂:
WITH RECURSIVE NodeHierarchy AS ( -- 锚点:初始化每个节点为自身的根节点 SELECT id, pid, weight, id AS root_id FROM Tree UNION ALL -- 递归:关联子节点,继承父节点的根ID SELECT child.id, child.pid, child.weight, parent.root_id FROM NodeHierarchy parent JOIN Tree child ON parent.id = child.pid ) -- 按根节点分组,计算子树总权重 SELECT root_id AS id, (SELECT pid FROM Tree WHERE id = root_id) AS pid, SUM(weight) AS sum FROM NodeHierarchy GROUP BY root_id ORDER BY root_id;
方式2:从叶子节点向上累加
这种方法从叶子节点开始,逐步向上累加父节点的权重与子树总和,适合层级较深的树结构:
WITH RECURSIVE SubTreeSum AS ( -- 锚点:叶子节点(没有子节点的节点)的自身权重即为子树总和 SELECT id, pid, weight AS sum_weight FROM Tree WHERE id NOT IN (SELECT pid FROM Tree WHERE pid IS NOT NULL) UNION ALL -- 递归:父节点的子树总和 = 自身权重 + 所有子节点的子树总和 SELECT t.id, t.pid, t.weight + s.sum_weight AS sum_weight FROM Tree t JOIN SubTreeSum s ON t.id = s.pid ) -- 汇总每个节点的所有子树总和,若没有子节点则取自身权重 SELECT t.id, t.pid, COALESCE(SUM(s.sum_weight), t.weight) AS sum FROM Tree t LEFT JOIN SubTreeSum s ON t.id = s.id GROUP BY t.id, t.pid, t.weight ORDER BY t.id;
验证
两种方法都能输出你需要的结果,可根据自己使用的数据库特性选择。比如方式1更直观,适合调试;方式2在深树场景下性能可能更优。
内容的提问来源于stack exchange,提问作者t232006
相关产品推荐
相关产品推荐

