2013-06-28 104 views
4

以下是需要编写SQL的数据设置。SQL中的复杂分层查询

Table:parchil 
par   chil 
-------------------- 
E1   E2 
E2   E3 
E3   E4 
E5   E6 
E7   E8 

Table:subval 
sub   val 
-------------------- 
E1   10 
E2   70 
E3   30 
E4   40 
E5   60 
E6   20 
E7   50 

Expected result: 
sub   val 
-------------------- 
E1   150 
E2   140 
E3   70 
E4   40 
E5   80 
E6   20 
E7   50 

我有以下查询到目前为止,这是冗长的,远离优雅。

select a.par,sum(b.val) from 
(select 'E1' as par,'E1' as chil from dual 
union all 
select 
    'E1' as par, chil 
from 
    parchil 
start with par='E1' 
connect by prior chil=par 
union all 
select 'E2' as par,'E2' as chil from dual 
union all 
select 
    'E2' as par, chil 
from 
    parchil 
start with par='E2' 
connect by prior chil=par 
union all 
select 'E3' as par,'E3' as chil from dual 
union all 
select 
    'E3' as par, chil 
from 
    parchil 
start with par='E3' 
connect by prior chil=par 
union all 
select 'E4' as par,'E4' as chil from dual 
union all 
select 
    'E4' as par, chil 
from 
    parchil 
start with par='E4' 
connect by prior chil=par 
union all 
select 'E5' as par,'E5' as chil from dual 
union all 
select 
    'E5' as par, chil 
from 
    parchil 
start with par='E5' 
connect by prior chil=par 
union all 
select 'E6' as par,'E6' as chil from dual 
union all 
select 
    'E6' as par, chil 
from 
    parchil 
start with par='E6' 
connect by prior chil=par 
union all 
select 'E7' as par,'E7' as chil from dual 
union all 
select 
    'E7' as par, chil 
from 
    parchil 
start with par='E7' 
connect by prior chil=par 
) a, 
subval b 
where 
a.chil=b.sub 
group by a.par 
order by a.par; 

有没有办法解决这个优雅?谢谢。

+0

为什么E4在预期的结果,但不是E8 – schurik

回答

3

可以使用cte做到这一点;

WITH cte(sub,val,par,chil, lev) AS (
    SELECT s.sub, s.val, p.par, p.chil, 1 
    FROM subval s LEFT JOIN parchil p ON s.sub=p.par 
    UNION ALL 
    SELECT s.sub, s.val+c.val, p.par, p.chil, lev + 1 
    FROM subval s LEFT JOIN parchil p ON s.sub=p.par 
    JOIN cte c ON c.sub=p.chil 
) 
SELECT c1.sub,c1.val FROM cte c1 
LEFT JOIN cte c2 
    ON c1.sub=c2.sub 
AND c1.lev < c2.lev 
WHERE c2.sub IS NULL 
ORDER BY sub; 

An SQLfiddle to test with

...或者您可以使用常规的分层查询;

SELECT root, SUM(val) val 
FROM 
( 
    SELECT CONNECT_BY_ROOT sub root, val 
    FROM subval s 
    LEFT JOIN parchil p ON s.sub = p.par 
    CONNECT BY sub = PRIOR chil 
) 
GROUP BY root 
ORDER BY root 

Another SQLfiddle

+0

:Awsome解决方案:) –

+1

解决方案的荣誉。感谢编辑这个问题! – digdug

3

可以使用CONNECT_BY_ROOT

select root, sum(val) 
from 
(select chil, connect_by_root par root 
    from parchil 
    connect by par = prior chil 
    start with par in (select par from parchil) 
    union all 
    select par, par from parchil 
) 
, subval 
where 
    sub=chil 
group by root 
order by root 
;