感谢您添加输入和预期输出数据 - 这使我们更容易确保我们得到您期望的答案!
这是一种方法:
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)。
那么就很简单了,加入 trans 表并进行汇总计数。
考虑到层次结构只有两个可能的级别,这是一种(希望更快!)修改后的方法来做同样的事情:
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