SQL Server查询会计科目表的分层组明智总和

时间:2015-04-14 06:38:15

标签: sql sql-server recursive-query

我创建了一个显示帐户名称和余额的查询,如下所示。

表结构如下。

Level      Account                Balance  AccountCode  ParentAccountCode

1      Revenue                          0           41         NULL
2      Direct Income                    0          411           41
3      Sales                            0         4111          411
4      Sales                            0        41111         4111
5      In Store Sales                 100       411111        41111
5      Online Sales                   200       411112        41111
2      Indirect Income                  0          412           41
3      Interest                         0         4121          412
4      Bank Interest                    0        41211         4121
5      Bank Interest A                400       412111        41211 
5      Bank Interest B                700       412112        41211
3      Other Income                     0         4122          412
4      Other Income                     0        41221         4122
5      Other Income                   900       412211        41221

以上所有字段均来自同一张表。

但只有5级帐户才有余额。

我想编写sql查询,以层次和层次方式显示父帐户中子帐户的帐户添加。

预期结果如下

Level      Account                              Balance

1         Revenue                                  2300
2         Direct Income                             300
3         Sales                                     300
4         Sales                                     300
5         In Store Sales                            100
5         Online Sales                              200
2         Indirect Income                          2000
3         Interest                                 1100
4         Bank Interest                            1100
5         Bank Interest A                           400
5         Bank Interest B                           700
3         Other Income                              900
4         Other Income                              900
5         Other Income                              900

感谢。

1 个答案:

答案 0 :(得分:2)

编辑以匹配您的结构:

with AccountBalanceHierarchy as
(
-- root level
select AccountCode
     , ParentAccountCode
     , Account
     , 1 as [Level]
     , cast('-' + cast (AccountCode as nvarchar(10)) + '-' as nvarchar(100)) as Hierarchy -- build hierarchy in format -L0-L1-L2-...-Ln--
     , Balance 
  from AccountBalance 
 where ParentAccountCode is null
 union all
  -- recursive join on parent, building hierarchy
select CurrentLevel.AccountCode
     , CurrentLevel.ParentAccountCode
     , CurrentLevel.Account
     , ParentLevel.[Level]+1 as [Level]
     , cast(ParentLevel.Hierarchy + cast (CurrentLevel.AccountCode as nvarchar(10))+ '-' as nvarchar(100)) as Hierarchy
     , CurrentLevel.Balance
  from AccountBalance CurrentLevel
  join AccountBalanceHierarchy ParentLevel on CurrentLevel.ParentAccountCode = ParentLevel.AccountCode
)
select CurrentHierarchyLevel.[Level]
     , replicate('    ', CurrentHierarchyLevel.[Level]) + CurrentHierarchyLevel.Account as Account
     , sum(case when CurrentHierarchyLevel.Hierarchy = substring(ChildLevel.Hierarchy, 1, len(CurrentHierarchyLevel.Hierarchy)) then ChildLevel.Balance else 0 end)
  from AccountBalanceHierarchy as CurrentHierarchyLevel
 cross 
  join AccountBalanceHierarchy as ChildLevel
 group by CurrentHierarchyLevel.[Level], CurrentHierarchyLevel.Account,CurrentHierarchyLevel.Hierarchy
 order by CurrentHierarchyLevel.Hierarchy

<强>解释

在层次结构CTE中,我们构建从根级别开始的节点层次结构(其中ParentAccountCode为null)然后我们通过ParentAccountCOde = AccountCode连接其他级别,同时增加级别。

在CTE中,我们还为每个节点以-L0-L1 -...- Ln的形式构建节点的平面结构。根将具有-41-的结构,然后其ID为411和412的子将具有结构-41-411-和-41-4112-,411的子代码为4111将为-41-411 -4111-。你的帐户代码实际上是不必要的,因为它们相互匹配,但我觉得它们可能不一定是真正的 ID,因为你刚刚编辑了几次你的问题。像代码一样构建结构的解决方案使得帐户的ID不受限制。

然后我们最终从CTE中选择并获得所有交叉连接所有节点的平衡,并将生成的子平面结构与当前结构相匹配。我们知道给定节点的子节点将具有与父节点相同的结构开头。上面的示例:具有结构-1-的根项目1的所有子项将在开头具有-1-,例如, -1-3-, - 1-3-5 - , - 1-2-;或者所有-1-3-5-的孩子在开始时将具有-1-3-5-(例如-1-3-5-10)。这是通过使用CASE语句在SUM中完成的 - 如果结构的开头匹配(子结构的子串等于父结构),则使用current_value求和。

这是包含架构和查询http://sqlfiddle.com/#!6/09ec8/1的sqlfiddle以及与预期结果相符的结果数据:

Level       Account                                    Balance
----------- ------------------------------------------ ---------------------
1               Revenue                                2300,00
2                   Direct Income                      300,00
3                       Sales                          300,00
4                           Sales                      300,00
5                               In Store Sales         100,00
5                               Online Sales           200,00
2                   Indirect Income                    2000,00
3                       Interest                       1100,00
4                           Bank Interest              1100,00
5                               Bank Interest A        400,00
5                               Bank Interest B        700,00
3                       Other Income                   900,00
4                           Other Income               900,00
5                               Other Income           900,00