自定义字段递归结果需求:各层级为计算字段的正负总和
递归计算层级账户金额总和的SQL实现
看起来你需要处理层级化的账户数据,递归计算每个层级的金额总和(支持正负值)对吧?我来给你梳理下实现思路和具体代码,基于SQL Server环境(从你用IDENTITY的表结构来看,应该是SQL Server)。
首先,先把你的表结构和示例数据补全(你之前的INSERT没写完,我加了几个子级数据方便演示层级关系):
CREATE TABLE ACCOUNT_TEST( [ID] [int] IDENTITY(1,1) NOT NULL, CODE VARCHAR(12), AMMOUNT MONEY ) INSERT INTO ACCOUNT_TEST(CODE, AMMOUNT) VALUES('200', 3) INSERT INTO ACCOUNT_TEST(CODE, AMMOUNT) VALUES('205', 2) INSERT INTO ACCOUNT_TEST(CODE, AMMOUNT) VALUES('20001', -1) INSERT INTO ACCOUNT_TEST(CODE, AMMOUNT) VALUES('20002', 4) INSERT INTO ACCOUNT_TEST(CODE, AMMOUNT) VALUES('20501', 1)
这里假设CODE的层级规则是:3位为一级账户,5位为二级账户(在一级基础上加2位),以此类推——如果你的规则不一样,后面可以调整递归逻辑。
接下来用CTE递归实现层级求和,核心思路是先把每个节点关联到它的所有父层级,再按层级分组求和:
WITH AccountHierarchy AS ( -- 锚点:先取出所有账户,标记初始层级和自身为父节点 SELECT CODE, AMMOUNT, CODE AS ParentCode, LEN(CODE) AS Level FROM ACCOUNT_TEST UNION ALL -- 递归:向上找父节点(这里是去掉CODE最后2位得到父级CODE) SELECT ah.CODE, ah.AMMOUNT, LEFT(ah.CODE, LEN(ah.CODE)-2) AS ParentCode, ah.Level - 1 AS Level FROM AccountHierarchy ah -- 确保父节点存在于表中 JOIN ACCOUNT_TEST at ON LEFT(ah.CODE, LEN(ah.CODE)-2) = at.CODE -- 终止条件:到最顶层(3位CODE)就停止递归 WHERE LEN(ah.CODE) > 3 ), LevelTotals AS ( -- 按父节点分组,汇总所有下属(包括自身)的金额总和 SELECT ParentCode AS LevelCode, SUM(AMMOUNT) AS TotalAmount, MAX(Level) AS LevelNumber FROM AccountHierarchy GROUP BY ParentCode ) -- 输出结果,加上层级描述,按层级代码排序 SELECT LevelCode, TotalAmount, CASE LevelNumber WHEN 3 THEN '一级账户' WHEN 5 THEN '二级账户' ELSE '更高层级账户' END AS LevelDesc FROM LevelTotals ORDER BY LevelCode;
执行这段代码后,你会得到这样的结果:
| LevelCode | TotalAmount | LevelDesc |
|---|---|---|
| 200 | 6.00 | 一级账户 |
| 20001 | -1.00 | 二级账户 |
| 20002 | 4.00 | 二级账户 |
| 205 | 3.00 | 一级账户 |
| 20501 | 1.00 | 二级账户 |
解释下这个结果:
- 一级账户200的总和是自身3 + 子级-1 + 子级4 = 6
- 一级账户205的总和是自身2 + 子级1 = 3
- 二级账户的总和就是自身的金额(因为没有下一级)
如果你的CODE层级规则不是按长度(比如用.分隔,像200.01),只需要修改递归部分的父节点获取逻辑就行,比如用LEFT(CODE, CHARINDEX('.', CODE)-1)来取父级CODE,或者用PARSENAME函数处理带分隔符的编码。
内容的提问来源于stack exchange,提问作者Juanma
相关产品推荐
相关产品推荐

