[英]How to SUM all subchildren tree in SQL recursively?
美好的一天,我已經在這個問題上拉了一段時間的頭發><"
我在樹結構中有4 個類別。
租戶類別事務視圖:
我已經非常接近了......但有些東西我沒有得到><“
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
上述查詢的結果:
看來我正在生成正確的 treeSum 但只在一個分支中顛倒
你會這么好心幫我一把嗎?
感謝您的時間:)
試試這個。 首先,我們遞歸地找到所有的分支列表。 每個分支都由相應的根標識。 然后,我們聚合每個根/分支的節點數量。
注意:樹的頂部不應有 null id。 這將違反主鍵約束。 然而,頂層節點的父節點可以是 null。 我在我的測試用例中糾正了這一點。
此外,我可以通過遞歸攜帶根行值(對於每個分支),避免最終連接。
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
;
根 | idParentCategory | 總和小計 | 總數量 | 全部的 |
---|---|---|---|---|
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 |
此外,這可以寫入基於 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
;
最后,我們可以通過在遞歸邏輯中攜帶其他根值來刪除最后一個 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
;
設置:
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)
;
解決方案實際上很簡單:-)
附言
“遞歸”查詢沒有遞歸。 這是一個誤導性的名稱。 這些實際上是迭代查詢,而不是遞歸的。
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.