sql query (id,parentId) 结构中的层级累加和
Hierarchical cumulative sum in sql query (id,parentId) structure
我有两个表,我想获取所有帐户及其贷方金额和借方金额
甚至父记录也必须对它们的子值求和
我正在实施 Id ParentId 结构。
1- [AccountChart] Table 具有这些字段:
Id smallint
ParentId smallint Null
AccountName nvarchar(100)
2- [交易] Table 具有这些字段
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
我喜欢使用范围键的技巧。 如果您的层次结构移动缓慢,我会创建一个table来存储这些值
只是为了扩展,范围键方便选择,和可变深度聚合。
您可能会注意到 SEQ
有一个 Order by AccountName
。在我的 GL 系统中,我们有一列用于表示顺序。这控制顺序而不是帐户上名称或有效数字的字母顺序。
例子
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
我有两个表,我想获取所有帐户及其贷方金额和借方金额 甚至父记录也必须对它们的子值求和
我正在实施 Id ParentId 结构。
1- [AccountChart] Table 具有这些字段:
Id smallint
ParentId smallint Null
AccountName nvarchar(100)
2- [交易] Table 具有这些字段
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
我喜欢使用范围键的技巧。 如果您的层次结构移动缓慢,我会创建一个table来存储这些值
只是为了扩展,范围键方便选择,和可变深度聚合。
您可能会注意到 SEQ
有一个 Order by AccountName
。在我的 GL 系统中,我们有一列用于表示顺序。这控制顺序而不是帐户上名称或有效数字的字母顺序。
例子
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