[英]How to SUM all subchildren tree in SQL recursively?
Good day, I've been pulling my hair on this problem for a while ><"美好的一天,我已经在这个问题上拉了一段时间的头发><"
I have 4 categories in a tree structure.我在树结构中有4 个类别。
tenant_category_transaction_view:租户类别事务视图:
I've managed to come very close... But there's something I don't get ><"我已经非常接近了......但有些东西我没有得到><“
with recursive cte (sumSubtotal, sumQuantity, id, idParentCategory, treeSum, depth) as (
select root.sumSubtotal, -- STEP 1
root.sumQuantity,
root.id,
root.idParentCategory,
root.sumSubtotal as treeSum,
0 as depth
from tenant_category_transaction_view as root
union all -- LOOP THROUGH ALL ROOT ROWS AND ADD ROWS TO THE CTE WITH THE INNER JOIN
select child.sumSubtotal, -- STEP 3
child.sumQuantity,
child.id,
child.idParentCategory,
(cte.treeSum + child.sumSubtotal) AS treeSum,
(cte.depth + 1) AS depth
from tenant_category_transaction_view AS child
inner join cte on child.idParentCategory = cte.id -- STEP 2
)
select sumSubtotal, sumQuantity, id, idParentCategory, treeSum, depth -- STEP 4
from cte
Result of the above query:上述查询的结果:
It seems I'm generating the correct treeSum but upside down in only one branch看来我正在生成正确的 treeSum 但只在一个分支中颠倒
Would you be so kind to give me a hand?你会这么好心帮我一把吗?
Thank you for your time:)感谢您的时间:)
Try this one.试试这个。 First, we find all the branch lists recursively.
首先,我们递归地找到所有的分支列表。 Each branch is identified by a corresponding root.
每个分支都由相应的根标识。 Then, we aggregate the node quantities for each root/branch.
然后,我们聚合每个根/分支的节点数量。
Note: The top of the tree shouldn't have a null id.注意:树的顶部不应有 null id。 That would violate the primary key constraint.
这将违反主键约束。 The parent of the top node can be null, however.
然而,顶层节点的父节点可以是 null。 I corrected that in my test case.
我在我的测试用例中纠正了这一点。
Also, I could have carried the root row values (for each branch) through the recursion, avoiding the final join.此外,我可以通过递归携带根行值(对于每个分支),避免最终连接。
WITH RECURSIVE cte AS (
SELECT t.*, t.id AS root
FROM tenant_category_transaction_view AS t
UNION ALL
SELECT t.*, t0.root
FROM cte AS t0
JOIN tenant_category_transaction_view AS t
ON t.idParentCategory = t0.id
)
SELECT root
, MIN(t2.idParentCategory) AS idParentCategory
, MIN(t2.sumSubtotal) AS sumSubtotal
, MIN(t2.sumQuantity) AS sumQuantity
, SUM(t1.sumSubtotal) AS total
FROM cte AS t1
JOIN tenant_category_transaction_view AS t2
ON t1.root = t2.id
GROUP BY root
ORDER BY root
;
root![]() |
idParentCategory ![]() |
sumSubtotal![]() |
sumQuantity![]() |
total![]() |
---|---|---|---|---|
1 ![]() |
null ![]() |
0 ![]() |
98 ![]() |
9890 ![]() |
2 ![]() |
1 ![]() |
9800 ![]() |
1 ![]() |
9800 ![]() |
4 ![]() |
1 ![]() |
20 ![]() |
1 ![]() |
90 ![]() |
5 ![]() |
4 ![]() |
30 ![]() |
1 ![]() |
70 ![]() |
6 ![]() |
5 ![]() |
40 ![]() |
1 ![]() |
40 ![]() |
Additionally, this can be written to aggregate based on t2.id, which is the primary key, allowing slight simplification, due to functional dependence.此外,这可以写入基于 t2.id 的聚合,这是主键,由于功能依赖性,允许稍微简化。
WITH RECURSIVE cte AS (
SELECT t.*, t.id AS root
FROM tenant_category_transaction_view AS t
UNION ALL
SELECT t.*, t0.root
FROM cte AS t0
JOIN tenant_category_transaction_view AS t
ON t.idParentCategory = t0.id
)
SELECT t2.id
, t2.idParentCategory
, t2.sumSubtotal
, t2.sumQuantity
, SUM(t1.sumSubtotal) AS total
FROM cte AS t1
JOIN tenant_category_transaction_view AS t2
ON t1.root = t2.id
GROUP BY t2.id
ORDER BY t2.id
;
Finally, we can remove the last JOIN by carrying other root values within the recursive logic:最后,我们可以通过在递归逻辑中携带其他根值来删除最后一个 JOIN:
WITH RECURSIVE cte AS (
SELECT t.*, t.id AS root
, idParentCategory AS idParentCategory0
, sumSubtotal AS sumSubtotal0
, sumQuantity AS sumQuantity0
FROM tenant_category_transaction_view AS t
UNION ALL
SELECT t.* , t0.root
, t0.idParentCategory0
, t0.sumSubtotal0
, t0.sumQuantity0
FROM cte AS t0
JOIN tenant_category_transaction_view AS t
ON t.idParentCategory = t0.id
)
SELECT root
, MIN(idParentCategory0) AS idParentCategory
, MIN(sumSubtotal0) AS sumSubtotal
, MIN(sumQuantity0) AS sumQuantity
, SUM(t1.sumSubtotal) AS total
FROM cte AS t1
GROUP BY root
ORDER BY root
;
The setup:设置:
CREATE TABLE tenant_category_transaction_view (
id int primary key
, idParentCategory int
, sumSubtotal int
, sumQuantity int
);
INSERT INTO tenant_category_transaction_view VALUES
(1, null, 0, 0)
, (2, 1, 9800, 98)
, (4, 1, 20, 1)
, (5, 4, 30, 1)
, (6, 5, 40, 1)
;
The solution is actually quite simple:-)解决方案实际上很简单:-)
PS附言
There is nothing recursive about "recursive" queries. “递归”查询没有递归。 It is a misleading name.
这是一个误导性的名称。 Those are actually iterative queries, not recursive.
这些实际上是迭代查询,而不是递归的。
with recursive cte (root_id, id, sumSubtotal) as
(
select null
,null
,0
union all
select id
,id
,sumSubtotal
from tenant_category_transaction_view as tctv
union all
select cte.root_id
,tctv.id
,tctv.sumSubtotal
from cte
join tenant_category_transaction_view as tctv
on tctv.idParentCategory <=> cte.id
)
select root_id
,sum(sumSubtotal)
from cte
group by root_id
+---------+-------------+
| root_id | sumSubtotal |
+---------+-------------+
| null | 9890 |
| 1 | 9800 |
| 4 | 90 |
| 5 | 70 |
| 6 | 40 |
+---------+-------------+
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.