2015-04-14 1 views
1

У меня есть три таблицы Учетные записи (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 

I знаю, что я должен сделать присоединиться к 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 

но Я не понимаю ищем то, что я ищу.

редактировать .. добавлены ключи к таблицам

К сожалению у меня была ошибка в результате им lokking для, я только нужна полная Древа счетов, которые actualy ссылка на МВЗ не все учетные записи для каждого МВЗ, поэтому крест-соединение дает мне больше строк, чем те, которые мне нужны, опять жаль, что не объяснил себя правильно.

Я использую Oracle 11g r2

ответ

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

Пожалуйста, обратите внимание, что результат не содержит строку с идентификатором = 111. Это не ребенок и не родитель 112, я подозреваю, что это ошибка в выходе, создаваемом вручную. Нет никакой логической причины, чтобы показать эту строку.

В SQL мы начинаем с определенной точки (учетная запись из apcc) и создаем два иерархических подзапроса двумя способами. Затем мы объединяем их. Заключительный запрос сортирует и перечисляет уровни.

+0

спасибо за ответ, это именно то, что я пытался сделать, но я не знал, как снова так много. и да строка с идентификатором 111 была ошибкой, когда я попытался сгенерировать пример данных, которые я хотел – Lara

+0

Хороший вопрос, рад, что я мог бы помочь .. –

+0

Я подумал об этом вопросе немного больше, и я думаю, что в предпоследней строке вы можете использовать [dense_rank] (http://www.techonthenet.com/oracle/functions/dense_rank.php) вместо [ранга] (http://www.techonthenet.com/oracle/functions/rank.php) - используйте тот, который вам подходит. –

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, и нет очевидного естественного соединения.

Смежные вопросы