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

时间:2015-04-14 11:57:29

标签: sql oracle hierarchical-data

我有3个表帐户(id,name,parent),CostCenters(id,name,parent)和AccountPerCostCenter(account,costcente)前两个是分层表,最后一个是我用来链接它们的表

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

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);

您可以看到并非所有帐户都是指向成本中心的链接,并且链接可以位于树的任何级别。所以我想要得到的是每个成本中心的完整帐户树,我用

获取帐户树
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

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

编辑.. 将键添加到表

抱歉,我在结果中遇到了错误,我只需要完整的树 实际的帐户链接到成本中心而不是每个成本中心的所有帐户,因此交叉连接给了我比我需要的更多的行,再次抱歉没有以正确的方式解释自己。

我正在使用oracle 11g r2

2 个答案:

答案 0 :(得分:0)

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

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中包含任何外键,也没有明显的自然连接。

答案 1 :(得分:0)

似乎每个帐户都需要找到他的父母,祖父母,子女,孙子女等。此查询执行此操作:

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的行。它不是112的孩子也不是父母,我怀疑这是手工生成的输出中的错误。 显示这一行没有合理的理由。

在SQL中,我们从某一点开始(来自apcc的帐户)并以两种方式构建两个分层子查询。接下来我们联合他们。最终查询排序和枚举级别。