2013-06-28 103 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 
;