SQL查询中的分层累积总和(id,parentId)结构

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

我有两个表格,我想获取所有帐户及其贷方总和和借方总和甚至父记录也必须将其子值相加

我正在实现ID ParentId结构。

1- [AccountChart]包含这些字段的表:

Id smallint
ParentId smallint Null
AccountName nvarchar(100)

2-具有这些字段的[交易]表

AccountId smallInt
TransactionDate DateTime
Debit decimal(19,5)
Credit decimal(19,5)

这是我尝试过的

    Create table [AccountChart] (
    id int not null,
    parentId int null,
    AccountName nvarchar(100)

    PRIMARY KEY (ID)
      )

    Create table [TransactionData] (
    id int not null,
    TransactionDate DateTime not null,
    AccountId int not null,
    Credit decimal(19,5),
    Debit decimal(19,5)

    PRIMARY KEY (ID)
    )

    insert into [AccountChart] (id,parentId,AccountName) values (1,null,'level 0');
    insert into [AccountChart] (id,parentId,AccountName) values (2,1,'level 2');
    insert into [AccountChart] (id,parentId,AccountName) values (3,2,'level 3 - 1');
    insert into [AccountChart] (id,parentId,AccountName) values (4,2,'level 3 - 2 ');


    insert into [TransactionData] (id,TransactionDate,AccountId,Credit,Debit) values (1,'2020-03-17',3,1000.0,0.0)
    insert into [TransactionData] (id,TransactionDate,AccountId,Credit,Debit) values (2,'2020-03-17',3,0.0,1000.0)
    insert into [TransactionData] (id,TransactionDate,AccountId,Credit,Debit) values (3,'2020-03-17',4,4000.0,0.0)
    insert into [TransactionData] (id,TransactionDate,AccountId,Credit,Debit) values (4,'2020-03-17',3,6000.0,0.0)
    insert into [TransactionData] (id,TransactionDate,AccountId,Credit,Debit) values (5,'2020-03-17',4,3000.0,0.0)


    ;WITH cteBalances (AccountId, ParentId, Credit, Debit)
    AS (SELECT
      AccountChart.Id,
      AccountChart.ParentId,
      SUM([TransactionData].Credit) AS Credit,
      SUM([TransactionData].Debit) AS Debit
     FROM [TransactionData]
     INNER JOIN AccountChart ON ([TransactionData].AccountId = AccountChart.Id)
     GROUP BY AccountChart.Id,AccountChart.ParentId)

    SELECT
      AccountChart.id,
      AccountChart.ParentId,
      AccountChart.AccountName,
      cteBalances.Credit,
      cteBalances.Debit
    FROM  AccountChart 
    left JOIN cteBalances ON (AccountChart.ID = cteBalances.AccountID)

我无法携带父记录的摘要值的问题。

我得到的结果是:

id  ParentId    AccountName   Credit        Debit
1   NULL        level 0       NULL          NULL
2   1           level 2       NULL          NULL
3   2           level 3 - 1   7000.00000    1000.00000
4   2           level 3 - 2   7000.00000    0.00000

但是我希望以此来计算父母中的孩子

id  ParentId    AccountName   Credit        Debit
1   NULL        level 0       14000.00000   1000.00000
2   1           level 2       14000.00000   1000.00000
3   2           level 3 - 1   7000.00000    1000.00000
4   2           level 3 - 2   7000.00000    0.00000
sql sql-server database reporting database-administration
1个回答
0
投票

我喜欢使用范围键的技术。 如果您的层次结构移动缓慢,我将创建一个表来存储这些值

仅需扩展,范围键便于选择和可变深度聚合。

您可能会注意到SEQ有一个Order by AccountName。在我的GL系统中,我们有一列表示顺序。这将控制顺序,而不是帐户名称或有效数字的ALPHA。

示例

Declare @Top  int         =  null   --<<  Sets top of Hier Try 2
Declare @Nest varchar(25) = '|---'  --<<  Optional: Added for readability

;with cteP as (
      Select Seq  = cast(10000+Row_Number() over (Order by AccountName) as varchar(500))
            ,ID
            ,ParentID 
            ,Lvl=1
            ,AccountName
      From   [AccountChart] 
      Where  IsNull(@Top,-1) = case when @Top is null then isnull(ParentID ,-1) else ID end
      Union  All
      Select Seq  = cast(concat(p.Seq,'.',10000+Row_Number() over (Order by r.AccountName)) as varchar(500))
            ,r.ID
            ,r.ParentID 
            ,p.Lvl+1
            ,r.AccountName
      From   [AccountChart] r
      Join   cteP p on r.ParentID  = p.ID)
     ,cteR1 as (Select *,R1=Row_Number() over (Order By Seq) From cteP)
     ,cteR2 as (Select A.ID,R2=Max(B.R1) From cteR1 A Join cteR1 B on (B.Seq like A.Seq+'%') Group By A.Seq,A.ID )
Select A.Lvl
      ,A.R1  
      ,B.R2
      ,A.ID
      ,A.ParentID 
      ,AccountName = max(Replicate(@Nest,A.Lvl-1) + A.AccountName)
      ,Credit      = sum(C.Credit)
      ,Debit       = sum(C.Debit)
 From cteR1 A
 Join cteR2 B on A.ID=B.ID
 Join (Select _R1=A.R1,B.* From cteR1 A Join [TransactionData] B on A.ID=B.AccountID ) C on (C._R1 between A.R1 and B.R2)
 Group By A.R1,B.R2,A.Lvl,A.ID,A.ParentID
 Order By A.R1

返回

enter image description here

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