感谢您添加输入和预期输出数据-这使我们更容易确保我们得到您期望的答案!
这里有一种方法:
with table_main as (select 1 H_ID, null Parent_ID, 1 TR_ID from dual union all
select 2 H_ID, 1 Parent_ID, NULL TR_ID from dual union all
select 3 H_ID, NULL Parent_ID, 2 TR_ID from dual union all
select 4 H_ID, NULL Parent_ID, 3 TR_ID from dual union all
select 5 H_ID, 4 Parent_ID, NULL TR_ID from dual union all
select 6 H_ID, 4 Parent_ID, NULL TR_ID from dual union all
select 7 H_ID, NULL Parent_ID, 4 TR_ID from dual union all
select 8 H_ID, 7 Parent_ID, NULL TR_ID from dual union all
select 9 H_ID, NULL Parent_ID, 5 TR_ID from dual union all
select 10 H_ID, 9 Parent_ID, NULL TR_ID from dual union all
select 11 H_ID, 9 Parent_ID, NULL TR_ID from dual union all
select 12 H_ID, 9 Parent_ID, NULL TR_ID from dual union all
select 13 H_ID, 9 Parent_ID, NULL TR_ID from dual union all
select 14 H_ID, 9 Parent_ID, NULL TR_ID from dual union all
select 15 H_ID, 9 Parent_ID, NULL TR_ID from dual union all
select 16 H_ID, 9 Parent_ID, NULL TR_ID from dual),
trans as (select 1 TR_ID, 45 XX_ID, to_date('12/01/2015', 'mm/dd/yyyy') Some_Date from dual union all
select 2 TR_ID, 4 XX_ID, to_date('12/01/2015', 'mm/dd/yyyy') Some_Date from dual union all
select 3 TR_ID, 6 XX_ID, to_date('12/20/2015', 'mm/dd/yyyy') Some_Date from dual union all
select 4 TR_ID, 45 XX_ID, to_date('12/01/2015', 'mm/dd/yyyy') Some_Date from dual union all
select 5 TR_ID, 23 XX_ID, to_date('12/22/2015', 'mm/dd/yyyy') Some_Date from dual)
-- end of mimicking your tables with data in them. See SQL below:
select tr1.some_date,
tr1.xx_id,
count(*) cnt
from (select h_id,
parent_id,
max(tr_id) over (partition by connect_by_root(h_id)) tr_id
from table_main tm
connect by prior h_id = parent_id
start with parent_id is null) tm1
inner join trans tr1 on (tm1.tr_id = tr1.tr_id)
group by tr1.some_date,
tr1.xx_id
order by tr1.some_date,
tr1.xx_id;
SOME_DATE XX_ID CNT
---------- ---------- ----------
12/01/2015 4 1
12/01/2015 45 4
12/20/2015 6 3
12/22/2015 23 8
基本上,这首先执行分层查询(
connect by...
)以链接父行和子行。
然后我们使用
connect_by_root
函数来标识所有父子行的顶层h_id。
一旦我们有了这些,我们就可以使用分析函数来返回每个顶层h_id的所有父行和子行的tr_id(我在这里使用了max(),因为看起来只有父行才会有tr_id)。
然后,连接到转换表并进行聚合计数就很简单了。
这里有一个(希望更快!)考虑到层次结构只有两个可能的层次,修改了做同样事情的方法:
with table_main as (select 1 H_ID, null Parent_ID, 1 TR_ID from dual union all
select 2 H_ID, 1 Parent_ID, NULL TR_ID from dual union all
select 3 H_ID, NULL Parent_ID, 2 TR_ID from dual union all
select 4 H_ID, NULL Parent_ID, 3 TR_ID from dual union all
select 5 H_ID, 4 Parent_ID, NULL TR_ID from dual union all
select 6 H_ID, 4 Parent_ID, NULL TR_ID from dual union all
select 7 H_ID, NULL Parent_ID, 4 TR_ID from dual union all
select 8 H_ID, 7 Parent_ID, NULL TR_ID from dual union all
select 9 H_ID, NULL Parent_ID, 5 TR_ID from dual union all
select 10 H_ID, 9 Parent_ID, NULL TR_ID from dual union all
select 11 H_ID, 9 Parent_ID, NULL TR_ID from dual union all
select 12 H_ID, 9 Parent_ID, NULL TR_ID from dual union all
select 13 H_ID, 9 Parent_ID, NULL TR_ID from dual union all
select 14 H_ID, 9 Parent_ID, NULL TR_ID from dual union all
select 15 H_ID, 9 Parent_ID, NULL TR_ID from dual union all
select 16 H_ID, 9 Parent_ID, NULL TR_ID from dual),
trans as (select 1 TR_ID, 45 XX_ID, to_date('12/01/2015', 'mm/dd/yyyy') Some_Date from dual union all
select 2 TR_ID, 4 XX_ID, to_date('12/01/2015', 'mm/dd/yyyy') Some_Date from dual union all
select 3 TR_ID, 6 XX_ID, to_date('12/20/2015', 'mm/dd/yyyy') Some_Date from dual union all
select 4 TR_ID, 45 XX_ID, to_date('12/01/2015', 'mm/dd/yyyy') Some_Date from dual union all
select 5 TR_ID, 23 XX_ID, to_date('12/22/2015', 'mm/dd/yyyy') Some_Date from dual)
-- end of mimicking your tables with data in them. See SQL below:
select tr.some_date,
tr.xx_id,
count(*) cnt
from table_main tm1
left join table_main tm2 on (tm1.h_id = coalesce(tm2.parent_id, tm2.h_id) and tm1.parent_id is null)
inner join trans tr on (tm1.tr_id = tr.tr_id)
group by tr.some_date,
tr.xx_id
order by tr.some_date,
tr.xx_id;
SOME_DATE XX_ID CNT
---------- ---------- ----------
12/01/2015 4 1
12/01/2015 45 4
12/20/2015 6 3
12/22/2015 23 8
另一个可能的答案不涉及自连接,但依赖于分析函数:
with table_main as (select 1 H_ID, null Parent_ID, 1 TR_ID from dual union all
select 2 H_ID, 1 Parent_ID, NULL TR_ID from dual union all
select 3 H_ID, NULL Parent_ID, 2 TR_ID from dual union all
select 4 H_ID, NULL Parent_ID, 3 TR_ID from dual union all
select 5 H_ID, 4 Parent_ID, NULL TR_ID from dual union all
select 6 H_ID, 4 Parent_ID, NULL TR_ID from dual union all
select 7 H_ID, NULL Parent_ID, 4 TR_ID from dual union all
select 8 H_ID, 7 Parent_ID, NULL TR_ID from dual union all
select 9 H_ID, NULL Parent_ID, 5 TR_ID from dual union all
select 10 H_ID, 9 Parent_ID, NULL TR_ID from dual union all
select 11 H_ID, 9 Parent_ID, NULL TR_ID from dual union all
select 12 H_ID, 9 Parent_ID, NULL TR_ID from dual union all
select 13 H_ID, 9 Parent_ID, NULL TR_ID from dual union all
select 14 H_ID, 9 Parent_ID, NULL TR_ID from dual union all
select 15 H_ID, 9 Parent_ID, NULL TR_ID from dual union all
select 16 H_ID, 9 Parent_ID, NULL TR_ID from dual),
trans as (select 1 TR_ID, 45 XX_ID, to_date('12/01/2015', 'mm/dd/yyyy') Some_Date from dual union all
select 2 TR_ID, 4 XX_ID, to_date('12/01/2015', 'mm/dd/yyyy') Some_Date from dual union all
select 3 TR_ID, 6 XX_ID, to_date('12/20/2015', 'mm/dd/yyyy') Some_Date from dual union all
select 4 TR_ID, 45 XX_ID, to_date('12/01/2015', 'mm/dd/yyyy') Some_Date from dual union all
select 5 TR_ID, 23 XX_ID, to_date('12/22/2015', 'mm/dd/yyyy') Some_Date from dual)
-- end of mimicking your tables with data in them. See SQL below:
select tr.some_date,
tr.xx_id,
count(*) cnt
from (select max(tr_id) over (partition by coalesce(parent_id, h_id)) tr_id
from table_main) tm1
inner join trans tr on (tm1.tr_id = tr.tr_id)
group by tr.some_date,
tr.xx_id
order by tr.some_date,
tr.xx_id;
SOME_DATE XX_ID CNT
---------- ---------- ----------
12/01/2015 4 1
12/01/2015 45 4
12/20/2015 6 3
12/22/2015 23 8