识别并标记分层结构中的每个分支

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

我正在为分类帐表创建一个清理视图,其中交易在源系统中以分层结构存储。我想创建一个附加列“Group_Id”来标识属于同一事务集的所有记录。

我的目标是找到填充

Group_Id
列的最有效方法,如下例所示:

条目_编号 已关闭_按_条目_否 组_Id
1 4 1
2 4 1
3 4 1
4 5 1
5 0 1
6 9 2
7 9 2
8 9 2
9 11 2
10 11 2
11 0 2
12 14 3
13 14 3
14 0 3
15 16 4
16 0 4
17 0 5
18 20 6
19 20 6
20 22 6
21 22 6
22 0 6

其中

Closed_By_Entry_No
Parent_Id
Entry_No
Child_Id
,每组最上面的
Parent_Id
Child_Id
始终为 0(零)。

我面临的挑战是我的数据集中没有一个层次结构,我有数十万个层次结构。通常,每组由两条记录组成:1 张发票 + 1 笔付款(总共占记录的 70%),但还有更详细的情况,如上面的示例,我可以使用例如15 张发票 + 3 笔付款 + 1 张贷方票据。我需要以一种可以将它们视为单个主题以进行进一步计算的方式来识别所有这些集合。

我现在解决这个问题的唯一想法是只用

提供光标
SELECT Entry_No, Closed_By_Entry_No 
FROM table 
WHERE Closed_By_Entry_No = 0

在结果集中滚动此游标,将每个候选记录发送到包含递归 CTE 的存储过程,以从原始表中读取层次结构,并从游标索引本身增量填充

Group_Id
并将结果存储在临时表中。然后从临时表继续......

必须有一种更简单的方法,既不使用游标也不使用临时表。

sql-server t-sql grouping common-table-expression hierarchy
1个回答
0
投票

这是一个简单的递归公用表表达式:

declare @LedgerEntries as Table ( Entry_No Int, Closed_By_Entry_No Int, Group_Id Int );
insert into @LedgerEntries ( Entry_No, Closed_By_Entry_No, Group_Id ) values
  ( 1, 4, 1 ),
  ( 2, 4, 1 ),
  ( 3, 4, 1 ),
  ( 4, 5, 1 ),
  ( 5, 0, 1 ),
  ( 6, 9, 2 ),
  ( 7, 9, 2 ),
  ( 8, 9, 2 ),
  ( 9, 11, 2 ),
  ( 10, 11, 2 ),
  ( 11, 0, 2 ),
  ( 12, 14, 3 ),
  ( 13, 14, 3 ),
  ( 14, 0, 3 ),
  ( 15, 16, 4 ),
  ( 16, 0, 4 ),
  ( 17, 0, 5 ),
  ( 18, 20, 6 ),
  ( 19, 20, 6 ),
  ( 20, 22, 6 ),
  ( 21,  22, 6 ),
  ( 22, 0, 6 );

select * from @LedgerEntries;

with Hierarchy as (
  -- Anchor query.
  --   Start with the closed by zero ledger entries and assign a group id.
  select Entry_No, Closed_By_Entry_No, Group_Id,
    Row_Number( ) over ( order by Entry_No ) as NewGroupId
    from @LedgerEntries
    where Closed_By_Entry_No = 0
  union all
  -- Recursive query.
  --   Add each level, working backwards, of ledger entries and propagate the new group id.
  select LE.Entry_No, LE.Closed_By_Entry_No, LE.Group_Id, H.NewGroupId
    from Hierarchy as H inner join
      @LedgerEntries as LE on LE.Closed_By_Entry_No = H.Entry_No
  )
  select *
    from Hierarchy
    order by Entry_No;

dbfiddle.

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