Tsql SQL Server CTE以递归方式获取给定行的所有链接行

Tsql SQL Server CTE以递归方式获取给定行的所有链接行,tsql,sql-server-2005,Tsql,Sql Server 2005,我有一张包含以下详细信息的表格: -- SQL CREATE TABLE [dbo].[LedgerTbl]( [LedgerID] [int] NOT NULL, [Name] [varchar](50) NOT NULL, [ParentID] [int] NULL, [Cr Amt] [decimal](8, 2) NOT NULL, [Dr Amt] [decimal](8, 2) NOT NULL, CONSTRAINT [PK_LedgerT

我有一张包含以下详细信息的表格:

-- SQL
CREATE TABLE [dbo].[LedgerTbl](
    [LedgerID] [int] NOT NULL,
    [Name] [varchar](50) NOT NULL,
    [ParentID] [int] NULL,
    [Cr Amt] [decimal](8, 2) NOT NULL,
    [Dr Amt] [decimal](8, 2) NOT NULL,
 CONSTRAINT [PK_LedgerTbl] PRIMARY KEY CLUSTERED 
(
    [LedgerID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
-- Data
INSERT [dbo].[LedgerTbl] ([LedgerID], [Name], [ParentID], [Cr Amt], [Dr Amt]) VALUES (17, N'L1 Ledger', 20, CAST(25252.00 AS Decimal(8, 2)), CAST(0.00 AS Decimal(8, 2)))
INSERT [dbo].[LedgerTbl] ([LedgerID], [Name], [ParentID], [Cr Amt], [Dr Amt]) VALUES (18, N'L2 Ledger', 20, CAST(9000.00 AS Decimal(8, 2)), CAST(0.00 AS Decimal(8, 2)))
INSERT [dbo].[LedgerTbl] ([LedgerID], [Name], [ParentID], [Cr Amt], [Dr Amt]) VALUES (20, N'Master Ledger', NULL, CAST(0.00 AS Decimal(8, 2)), CAST(6900.00 AS Decimal(8, 2)))
INSERT [dbo].[LedgerTbl] ([LedgerID], [Name], [ParentID], [Cr Amt], [Dr Amt]) VALUES (45, N'L1.1 Ledger', 17, CAST(361.00 AS Decimal(8, 2)), CAST(0.00 AS Decimal(8, 2)))
INSERT [dbo].[LedgerTbl] ([LedgerID], [Name], [ParentID], [Cr Amt], [Dr Amt]) VALUES (46, N'L1.1.1 Ledger', 45, CAST(6541.00 AS Decimal(8, 2)), CAST(0.00 AS Decimal(8, 2)))
INSERT [dbo].[LedgerTbl] ([LedgerID], [Name], [ParentID], [Cr Amt], [Dr Amt]) VALUES (47, N'L1.1.2 Ledger', 45, CAST(321.00 AS Decimal(8, 2)), CAST(0.00 AS Decimal(8, 2)))

GO
ALTER TABLE [dbo].[LedgerTbl]  WITH CHECK ADD  CONSTRAINT [FK_LedgerTbl_LedgerTbl] FOREIGN KEY([ParentID])
REFERENCES [dbo].[LedgerTbl] ([LedgerID])
GO
ALTER TABLE [dbo].[LedgerTbl] CHECK CONSTRAINT [FK_LedgerTbl_LedgerTbl]
GO
示例数据如下所示:

LedgerID    Name            ParentID     Cr Amt     Dr Amt
20          Master Ledger   NULL           0.00    6900.00
17          L1 Ledger       20         25252.00       0.00
18          L2 Ledger       20          9000.00       0.00
45          L1.1 Ledger     17           361.00       0.00
46          L1.1.1 Ledger   45          6541.00       0.00
47          L1.1.2 Ledger   45           321.00       0.00 
在上表的分类账20中,我需要所有链接的分类账(在所有级别),这些分类账直接或间接链接到此分类账。在上表中,所有分类账直接链接到20。
如果我查询分类账20的余额,它应该如下所示(添加所有级别的所有链接分类账的所有Cr金额和Dr金额):

由于所有分类账都直接或间接地与20挂钩,因此所有的Cr金额和Dr金额都在汇总。
将所有链接/未链接分类账的Cr金额和Dr金额相加后,结果应如下所示:

LedgerID   Tot. Cr Amt  Tot Dr Amt
20         41475.00    6900.00
18          9000.00       0.00
17         32475.00       0.00
45          7223.00       0.00
46          6541.00       0.00
47           321.00       0.00
请注意,分类账18没有任何子分类账,因此无需添加任何余额

请使用CTE或任何其他方法帮助实现这一点。提前谢谢

这就是我尝试过的:

;WITH RecursiveLedger(LedgerID, [Name],[Cr Amt], [Dr Amt], LevelNum, LevelIndex, ParentID)
AS (
       SELECT lg.LedgerID,
              lg.[Name],
              lg.[Cr Amt],
              lg.[Dr Amt],
              1 AS LevelNum,
              CAST(lg.LedgerID AS VARCHAR) AS LevelIndex,
              lg.ParentID 
       FROM   [LedgerTbl] lg
       WHERE  lg.ParentID IS NULL
       UNION ALL
       SELECT l.LedgerID,
              l.[Name],
              l.[Cr Amt],
              l.[Dr Amt],
              r.LevelNum + 1 AS LevelNum,
              CAST(r.LevelIndex + '.' + CAST(ROW_NUMBER() OVER(ORDER BY l.ParentID) AS VARCHAR) AS VARCHAR) AS LevelIndex,
              l.ParentID 
       FROM   [LedgerTbl] l,
              RecursiveLedger r
       WHERE  r.LedgerID = l.ParentID
   ) SELECT * FROM   RecursiveLedger

对于一个级别,我得到了结果,但对于多个级别,我无法使用CTE完成此操作。@Nagesh您可以在CTE上发布您的尝试吗?@Bridge我已经编辑并添加了我尝试过的内容。对于一个级别,我得到了结果,但对于多个级别,我无法使用CTE完成此操作。@Nagesh您能在CTE上发布您的尝试吗?@Bridge我已编辑并添加了我尝试过的内容。谢谢您的回答,但我需要Cr Amt和Dr Amt的总和。您能帮我(用sql)找出给定分类账的所有从属分类账吗?谢谢,请帮我找到分类账20的所有从属分类账及其从属分类账等等。@Nagesh。我已经扩展到包括所有层次结构的总和。这就是你想要的解决方案吗?谢谢你的回答,但我想要Cr Amt和Dr Amt的总和。您能帮我(用sql)找出给定分类账的所有从属分类账吗?谢谢,请帮我找到分类账20的所有从属分类账及其从属分类账等等。@Nagesh。我已经扩展到包括所有层次结构的总和。这就是你想要的解决方案吗?
;WITH RecursiveLedger(LedgerID, [Name],[Cr Amt], [Dr Amt], LevelNum, LevelIndex, ParentID)
AS (
       SELECT lg.LedgerID,
              lg.[Name],
              lg.[Cr Amt],
              lg.[Dr Amt],
              1 AS LevelNum,
              CAST(lg.LedgerID AS VARCHAR) AS LevelIndex,
              lg.ParentID 
       FROM   [LedgerTbl] lg
       WHERE  lg.ParentID IS NULL
       UNION ALL
       SELECT l.LedgerID,
              l.[Name],
              l.[Cr Amt],
              l.[Dr Amt],
              r.LevelNum + 1 AS LevelNum,
              CAST(r.LevelIndex + '.' + CAST(ROW_NUMBER() OVER(ORDER BY l.ParentID) AS VARCHAR) AS VARCHAR) AS LevelIndex,
              l.ParentID 
       FROM   [LedgerTbl] l,
              RecursiveLedger r
       WHERE  r.LedgerID = l.ParentID
   ) SELECT * FROM   RecursiveLedger
with anc as 
(
    select ledgerid, parentid
    from [LedgerTbl] where parentid is not null
    union all
    select c.ledgerid, isnull(anc.parentid, anc.parentid)
    from anc 
        inner join [LedgerTbl] c on anc.ledgerid = c.parentid
), anc2 as
(
    select * from anc
    union all
    select ledgerid, ledgerid
    from ledgertbl 
)
select  a.parentid,
        sum(l.[Cr Amt]), 
        sum(l.[dr Amt]) 
from anc2 a
    inner join ledgertbl l on a.ledgerid = l.ledgerid
group by a.parentid
order by a.parentid;