Sql server 基于汇总类型的树状结构中的总分
我试图计算树结构中每个节点的总计,计算总计取决于汇总类型 我有如下结构Sql server 基于汇总类型的树状结构中的总分,sql-server,ssms,Sql Server,Ssms,我试图计算树结构中每个节点的总计,计算总计取决于汇总类型 我有如下结构 如果节点类型为当前列表=查看当前节点,则无需在树中向下搜索 如果节点类型为子节点,则忽略当前节点并向下 如果节点类型为“当前”且子节点为“当前”,则包含当前节点 然后下去 假设我的起点是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 |
+--------+----------+------+------------+-------------------+------------------+
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
树表脚本:
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
我的尝试:
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;
查看实际情况。您是只想对D1
170
的总数进行汇总,还是需要知道单个总数70+100
示例数据脚本中存在键入错误。E2
的父项是D2
而不是它本身……示例数据脚本中还有另一个输入错误。D3
的父项是C3
,而不是C2
@Charlieface170@Sander我修好了it@sara你的树中有一个循环,在那里抱歉使用了带有打字错误的脚本。它的工作原理就像一个charm@Sander如果情况恰好是多亲,那么当起点为B1时,为什么B1会寻找其父代并获得重复分数?如果B1有多亲,那么这些父代中的每一个都会包含B1的子树值。这样的需求是一个很大的变化,当前的解决方案无法正确处理。请发布一个新问题,其中包含多个家长的数据样本和预期结果。一个新问题会比一个已经回答的问题得到更多的关注。@Sander你能研究一下这个问题吗