sql-server - 基于汇总类型的树结构中的总分数
问题描述
我正在尝试计算树结构的每个节点的总数,计算总数取决于汇总类型
我有如下结构
- 如果节点类型是当前列表= 查找当前节点,不需要我在树中向下走
- 如果节点类型为子节点= 忽略当前节点并往下走
- 如果节点类型是current 并且 child = I 包括当前节点并向下
假设我的起点是 B1 :所以总分 = (20 +40 +110 +60 +90)
假设我的起点 C2:分数是 110
我设法得到了所有的孩子,但是当涉及到汇总时,我被卡住了,请帮忙
示例数据脚本
+--------+----------+------+------------+-------------------+------------------+
| Teamid | ParentId | Name | ParentName | Type | Key Result Value |
+--------+----------+------+------------+-------------------+------------------+
| 1 | null | A1 | Null | Current and Child | 10 |
| 2 | 1 | B1 | A1 | Current and Child | 20 |
| 3 | 1 | B2 | A1 | Current and Child | 30 |
| 4 | 2 | C1 | B1 | Current List | 40 |
| 5 | 2 | C2 | B1 | Child List | 50 |
| 6 | 2 | C3 | B1 | Current and Child | 60 |
| 7 | 4 | D1 | C1 | Current and Child | 70 |
| 8 | 5 | D2 | C2 | Child List | 80 |
| 9 | 6 | D3 | C3 | Current and Child | 90 |
| 10 | 7 | E1 | D1 | Current List | 100 |
| 11 | 8 | E2 | D2 | Current and Child | 110 |
+--------+----------+------+------------+-------------------+------------------+
树表脚本:
CREATE TABLE TreeTable(
Teamid INTEGER NOT NULL PRIMARY KEY
,ParentId INTEGER
,Name VARCHAR(2) NOT NULL
,ParentName VARCHAR(4)
,Type VARCHAR(17) NOT NULL
,Key_Result_Value INTEGER NOT NULL
);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (1,NULL,'A1',NULL,'Current and Child',10);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (2,1,'B1','A1','Current and Child',20);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (3,1,'B2','A1','Current and Child',30);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (4,2,'C1','B1','Current List',40);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (5,2,'C2','B1','Child List',50);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (6,2,'C3','B1','Current and Child',60);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (7,4,'D1','C1','Current and Child',70);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (8,5,'D2','C2','Child List',80);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (9,6,'D3','C2','Current and Child',90);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (10,7,'E1','D1','Current List',100);
INSERT INTO TreeTable(Teamid,ParentId,Name,ParentName,Type,Key_Result_Value) VALUES (11,8,'E2','E2','Current and Child',110);
我的尝试:
WITH
CTE_Groups
AS
(
SELECT
TreeTable.teamid AS StartID
,TreeTable.Name AS StartName
,TreeTable.teamid
,TreeTable.ParentID
,TreeTable.Name
,1 AS Lvl
,TreeTable.Type
,TreeTable.Key_Result_Value
FROM TreeTable
UNION ALL
SELECT
CTE_Groups.StartID
,CTE_Groups.StartName
,TreeTable.teamid
,TreeTable.ParentID
,TreeTable.Name
,CTE_Groups.Lvl + 1 AS Lvl
,TreeTable.Type
,TreeTable.Key_Result_Value
FROM
TreeTable
INNER JOIN CTE_Groups ON CTE_Groups.teamid = TreeTable.ParentID
)
select * from CTE_Groups
order by startid,lvl
- 我尝试获取节点的所有子节点的屏幕截图,但后来我陷入了如何根据类型排除节点的问题,因为我需要了解完整路径:
+--------+-----------------------+
| TeamID | Score |
+--------+-----------------------+
| E1 | 100 |
| D1 | 70 + 100 |
| C1 | 40 |
| E2 | 110 |
| D2 | 110 |
| C2 | 110 |
| D3 | 90 |
| C3 | 60+90 |
| B1 | 20+40+110+60+90 |
| B2 | 30 |
| A1 | 10+30+20+40+110+60+90 |
+--------+-----------------------+
解决方案
使用递归列出子节点是一个好的开始。使用case
表达式,您还可以跟踪组类型以及何时添加或忽略值(忽略 = 使用0
而不是实际节点值)。
解决方案
with rcte as
(
select t.Name as GroupName,
t.Type as GroupType,
t.Name,
t.Type,
case t.Type
when 'Child list' then 0 -- if the current node must be ignored, then the current value changes to 0
else t.Key_Result_Value
end as Value
from TreeTable t
union all
select r.GroupName,
r.GroupType,
t.Name,
case r.Type
when 'Current list' then 'Current list' -- if the parent was the end of the sum, then it stays the end of the sum
else t.Type
end,
case
when r.Type = 'Current list' then 0 -- if the parent was the end of the sum, then the current value changes to 0
when t.Type = 'Child list' then 0 -- if the current node must be ignored, then the current value changes to 0
else t.Key_Result_Value
end
from rcte r
join TreeTable t
on t.ParentName = r.Name
)
select r.GroupName,
sum(r.Value) as GroupSum,
string_agg(case when r.Value <> 0 then convert(nvarchar(3), r.Value) end, '+') as GroupSumFormula
from rcte r
group by r.GroupName
order by r.GroupName;
结果
GroupName GroupSum GroupSumFormula
--------- -------- ---------------------
A1 360 10+20+30+40+60+90+110
B1 320 20+40+60+90+110
B2 30 30
C1 40 40
C2 110 110
C3 150 60+90
D1 170 100+70
D2 110 110
D3 90 90
E1 100 100
E2 110 110
小提琴以查看实际情况。
推荐阅读
- maven - 未能执行目标 org.codehaus.cargo:cargo-maven2-plugin:1.6.4:start
- r - optim() 没有给出正确的最小值
- dll - VSTS 构建 - 在构建的测试执行期间找不到编码的 UI 测试
- python - KeyError 问题:0
- javascript - 如何使用 Amplify with Javascript 返回 AWS 用户池中的用户状态?
- android - 从未使用过的观察者方法
- reactjs - 向 StatelessComponent 添加属性
- mysql - 外键创建了一个额外的列 mySQL
- sql-server - 我使用“INTERSECT”作为关键字搜索了 SQL Server 问题,但没有找到任何帮助
- hyperledger-fabric - Hyperledger - 构建您的第一个网络错误