在层次结构查询中显示父级的子值

show child value on parent in hierarchy query

我有这 3 个表 Accounts(id,name,parent), CostCenters(id,name,parent) 和 AccountPerCostCenter(account,costcente) 前两个是分层表,最后一个是我用来link 他们。

这里是创建和一些示例数据,以使我的问题更容易理解

Create table Accounts(id number, name varchar2(100), parent_id number);
insert into Accounts
Select 1, 'ACTIVE', null from dual union all
Select 11, 'CURRENT ASSETS', 1 from dual union all
Select 111, 'CASH AND CASH EQUIVALENTS', 11 from dual union all
Select 112, 'GENERAL BOX', 11 from dual union all
Select 12, 'GENERAL BOX', 1 from dual union all
Select 121, 'PETTY CASH', 12 from dual union all
Select 122, 'CASH IN BANKS', 12 from dual union all
Select 13, 'BANKS ACCOUNTS', 1 from dual union all
Select 131, 'CENTRAL BANK OF AMERICA', 13 from dual union all
Select 132, 'BANK PROMERICA', 13 from dual union all
select 133, 'BANK DAVIVIENDA', 13 from dual union all
select 1331, 'BANK SCOTIABANK', 133 from dual union all
select 1332, 'BANK PROMERICA EXEMPT', 133 from dual;

create table CostCenters (id number, name varchar2 (100), parent_id number);
insert into CostCenters
select 1, 'Cash flow from operating activities', null from dual union all
select 2, 'Adjustments to reconcile net (loss) to net cash (used)', 1 from dual union all
select 3, 'Provided by operations', 1 from dual union all
select 4, 'Depreciation', 3 from dual union all
select 5, 'Capital Increase Capitalization Accounts Payable to Shareholders', 3 from dual union all
select 6, 'Changes in Assets and Liabilities of the effects of Operation', null from dual union all
select 7, '(Increase) in Accounts Receivable', 6 from dual union all
select 8, 'Decrease in receivables related parties', 6 from dual;


create table AccountsPerCostCenters (account number, CostCenter number);
insert into AccountsPerCostCenters
select 112,2 from dual union all
select 133,4 from dual;

alter table accounts add constraint accounts_pk primary key (id);
alter table costcenters add constraint costcenters_pk primary key (id);
alter table accountspercostcenters add constraint accountspercostcenters_pk primary key (account, costcenter);

alter table accounts add constraint accounts_fk foreign key (parent_id)references accounts (id);
alter table costcenters add constraint costcenters_fk foreign key (parent_id)references costcenters (id);
alter table accountspercostcenters add constraint apcc_accounts_fk foreign key (account)references accounts (id);
alter table accountspercostcenters add constraint apcc_costcenters_fk foreign key (costcenter)references costcenters (id);

如您所见,并非所有帐户都作为成本中心的 link,并且 link 可以位于树的任何级别。所以我想要得到的是每个成本中心的完整账户树,我得到的账户树

select id, name, level  from accounts acc
connect by prior acc.id=acc.parent_id
start with acc.parent_id is null

id      name                        level
---------------------------------------------
1       ACTIVE                      1
11      CURRENT ASSETS              2
111     CASH AND CASH EQUIVALENTS   3
112     GENERAL BOX                 3
12      GENERAL BOX                 2
121     PETTY CASH                  3
122     CASH IN BANKS               3
13      BANKS ACCOUNTS              2
131     CENTRAL BANK OF AMERICA     3
132     BANK PROMERICA              3
133     BANK DAVIVIENDA             3
1331    BANK SCOTIABANK             4
1332    BANK PROMERICA EXEMPT       4

而我喜欢得到的是这样的东西

Id      Name                        Level    Cost Center
--------------------------------------------------------
1       ACTIVE                      1        112
11      CURRENT ASSETS              2        112
111     CASH AND CASH EQUIVALENTS   3        112
112     GENERAL BOX                 3        112
1       ACTIVE                      1        133
13      BANKS ACCOUNTS              2        133
133     BANK DAVIVIENDA             3        133
1331    BANK SCOTIABANK             4        133
1332    BANK PROMERICA EXEMPT       4        133

我知道我必须与 AccountsPerCostCenter 连接才能获得最后一列,但我不知道如何在所有行中获得它并获得每个成本中心的完整账户树我试试这个

Select acc.id, acc.name, level, apcc.costcenter
From accounts acc
    left join accountspercostcenters apcc on acc.id=apcc.account
connect by prior acc.id=acc.parent_id
start with acc.parent_id is null

但我没有得到任何我正在寻找的东西。

编辑.. 将键添加到表中

抱歉,我正在寻找的结果有误,我只需要完整的树 实际上 link 到成本中心的账户不是每个成本中心的所有账户所以交叉连接给我的行比我需要的多,再次抱歉没有以正确的方式解释我自己。

我正在使用 Oracle 11g r2

这为您提供了您描述的输出:

SELECT *
FROM   (
        select acc.id,
               acc.name,
               level AS depth
        from   accounts acc
        connect by prior acc.id=acc.parent_id
        start with acc.parent_id is null
       )
       CROSS JOIN
       AccountsPerCostCenters apcc;

不确定 CROSS JOIN 是否符合您的预期,或者是否有更好的方法链接两个表?您没有在 DDL 中包含任何外键,也没有明显的自然连接。

似乎对于每个帐户你都需要找到他的parents、grandparents、children、grandchildren 等等。此查询执行此操作:

with apcc as (select distinct account id from AccountsPerCostCenters),
a as (
  select id, name, decode(level, 1, 1, -level) l, connect_by_root(id) root
    from accounts 
    connect by prior parent_id = id
    start with id in (select id from apcc)
  union
  select id, name, level l, connect_by_root(id) root
    from accounts 
    connect by parent_id = prior id
    start with id in (select id from apcc) )
select id, name, 
    rank() over (partition by root order by l) lvl, root cost_center
  from a order by root, l

SQLFiddle demo

请注意结果不包含 id=111 的行。它不是 child 也不是 112 的 parent,我怀疑这是手动生成的输出错误。 显示此行没有合乎逻辑的理由。

在SQL中我们从某个点(apcc的account)开始,通过两种方式构建两个层次子查询。接下来我们将它们合并。最终查询排序和枚举级别。