I have two tables that I want to get all accounts and their Credit sum and Debit sum even parent records have to sum thier child values
I’m implementing Id ParentId Structure .
1- [AccountChart] Table with these fields :
Id smallint ParentId smallint Null AccountName nvarchar(100)
2- [Transaction] Table with these fields
AccountId smallInt TransactionDate DateTime Debit decimal(19,5) Credit decimal(19,5)
here is what I tried
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)
the problem that I couldn’t bring the summary values for the parent records.
the results I get is :
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
but I excpect to be calculate the childs in parent as this
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
Advertisement
Answer
I like the technique of using Range Keys. If you have a slow moving hierarchy, I would create a table to store these values
Just to expand, the range keys facilitate selection, and variable depth aggregation.
You may notice that the SEQ has an Order by AccountName. In my GL systems, we have a column for presentation sequence. This controls the order rather than ALPHA on name or significant digits on the account.
Example
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
Returns
