SQL Server 查询计算以下顶级 Childs 计算金额的总和

问题描述 投票:0回答:1

我有一个表TestPoolCalc,我需要显示当前节点数量+低于顶级Childs计算数量的总和。请查看预期输出

表格脚本和数据

 CREATE TABLE [dbo].[_TestPoolCalc](
    [PoolID] [varchar](50) NULL,
    [ParentPoolID] [varchar](50) NULL,
    [Amount] [numeric](18, 2) NULL
) ON [PRIMARY]
GO
INSERT [dbo].[_TestPoolCalc] ([PoolID], [ParentPoolID], [Amount]) VALUES (N'Pool 1
', N'ROOT', NULL)
GO
INSERT [dbo].[_TestPoolCalc] ([PoolID], [ParentPoolID], [Amount]) VALUES (N'Pool 1.1
', N'Pool 1
', NULL)
GO
INSERT [dbo].[_TestPoolCalc] ([PoolID], [ParentPoolID], [Amount]) VALUES (N'Pool 1.1.1
', N'Pool 1.1
', NULL)
GO
INSERT [dbo].[_TestPoolCalc] ([PoolID], [ParentPoolID], [Amount]) VALUES (N'Pool 1.1.1.1
', N'Pool 1.1.1
', CAST(-12500.00 AS Numeric(18, 2)))
GO
INSERT [dbo].[_TestPoolCalc] ([PoolID], [ParentPoolID], [Amount]) VALUES (N'Pool 1.1.1.2
', N'Pool 1.1.1
', CAST(-12500.00 AS Numeric(18, 2)))
GO
INSERT [dbo].[_TestPoolCalc] ([PoolID], [ParentPoolID], [Amount]) VALUES (N'Pool 1.1.2
', N'Pool 1.1
', CAST(-25000.00 AS Numeric(18, 2)))
GO
INSERT [dbo].[_TestPoolCalc] ([PoolID], [ParentPoolID], [Amount]) VALUES (N'Pool 1.2
', N'Pool 1
', CAST(25000.00 AS Numeric(18, 2)))
GO
INSERT [dbo].[_TestPoolCalc] ([PoolID], [ParentPoolID], [Amount]) VALUES (N'Pool 1.3', N'Pool 1
', CAST(-50000.00 AS Numeric(18, 2)))
GO
INSERT [dbo].[_TestPoolCalc] ([PoolID], [ParentPoolID], [Amount]) VALUES (N'Pool 2', N'ROOT', NULL)
GO
INSERT [dbo].[_TestPoolCalc] ([PoolID], [ParentPoolID], [Amount]) VALUES (N'Pool 2.1', N'Pool 2', NULL)
GO
INSERT [dbo].[_TestPoolCalc] ([PoolID], [ParentPoolID], [Amount]) VALUES (N'Pool 2.2', N'Pool 2', NULL)
GO
INSERT [dbo].[_TestPoolCalc] ([PoolID], [ParentPoolID], [Amount]) VALUES (N'Pool 2.3', N'Pool 2', CAST(75000.00 AS Numeric(18, 2)))
GO
INSERT [dbo].[_TestPoolCalc] ([PoolID], [ParentPoolID], [Amount]) VALUES (N'ROOT', NULL, NULL)
GO

我尝试过的方式

  WITH p AS (SELECT            
   a.ParentPoolID, a.PoolID 
   , CAST(a.PoolID AS VARCHAR(MAX)) AS path    
   , len(CAST(a.PoolID AS VARCHAR(MAX))) lpath    
   , a.Amount    
   
  FROM _TestPoolCalc a    
  WHERE a.ParentPoolID = 'Root'    
        UNION ALL    
  SELECT    
   pp.ParentPoolID, pp.PoolID   
   , p_2.path + '>' + pp.PoolID AS path    
   , len(p_2.path + '>' + pp.PoolID) lpath    
   , pp.Amount   
    
  FROM _TestPoolCalc pp     
     
  JOIN p AS p_2 ON pp.ParentPoolID = p_2.PoolID 
  )    
SELECT PoolID,ParentPoolID, path    
,Amount
,isnull((select sum(isnull(p1.Amount,0.0)) from p p1 where left(p1.path,p.lpath) = p.path and p.poolid <> p1.PoolId ),0) CalculatedAmount     
FROM  p
order by path

预期产量

# 矿池ID (A) 金额(B) 计算金额(C)
1 池1 -75000
B1+C2+C7+C8
2 泳池1.1 -50000
B2+C3+C6
3 矿池1.1.1 -25000
B3+C4+C5
4 矿池1.1.1.1 -12500.00 -12500
B4
5 矿池1.1.1.2 -12500.00 -12500
B5
6 矿池1.1.2 -25000.00 -25000
B6
7 泳池1.2 25000.00 25000
B7
8 泳池1.3 -50000.00 -50000
B8
9 泳池2 75000
B9+C10+C11+C12
10 池2.1 0
B10
11 泳池2.2 0
B11
12 泳池2.3 75000 75000
B12
sql-server hierarchical-data
1个回答
0
投票

使用您的测试数据:

WITH p AS (
    SELECT  poolid AS main, t.Amount, t.PoolID AS parent
    FROM    _TestPoolCalc t
    UNION ALL
    SELECT  p.main, tc.amount, tc.poolid
    FROM    p
    INNER JOIN _TestPoolCalc tc
        ON  tc.ParentPoolID = p.parent
  )    
SELECT  Main, ISNULL(SUM(Amount),0) AS total
FROM    p
GROUP BY Main

对于每个节点,我收集它及其下的所有子节点。通过将 PoolID 保留为主,收集最终结果变得非常容易,尽管此代码确实多次遍历级别,这可能会产生一些性能影响。

输出:

主要 总计
池1 -75000
泳池1.1 -50000
矿池1.1.1 -25000
矿池1.1.1.1 -12500
矿池1.1.1.2 -12500
矿池1.1.2 -25000
泳池1.2 25000
泳池1.3 -50000
泳池2 75000
池2.1 0
泳池2.2 0
泳池2.3 75000
0

如果你不感兴趣,你可以随时删除ROOT。

© www.soinside.com 2019 - 2024. All rights reserved.