2014-09-20 39 views
0

在Oracle 10g中,我有以下分级表:获取父数据,如果子数据是Oracle阶层表空

corp_id, parent_corp_id, col1, col2, col3 

我想变平的结构,使得我们得到的第一行的数据,其中COL1 OR col2或col3不为空。

因此,举例来说,假设我有:

corp_id = 1 
parent_corp_id = null 
col1 = 5 
col2 = NULL 
col3 = NULL 

corp_id = 3 
parent_corp_id = 1 
col1 = NULL 
col2 = NULL 
col3 = NULL 

此查询的结果会给我:

corp_id, parent_corp_id, col1, col2, col3 
3  , 1    , 5 , NULL, NULL 

另一种情形: 假设我把COL2 = 6,其中corp_id = 3

那么,结果集应该是:

corp_id, parent_corp_id, col1, col2, col3 
3  , 1    , NULL, 6, NULL 

换句话说,如果孩子在这三列中有一列有数据,我们就抓住它。否则,我们尝试父母等,等等。不应该超过3个级别,但可以有3个级别进行研究。

对分层查询来说很新,所以如果这是一个基本问题,请原谅我。

回答

0

使用coalesce()功能,在其列表返回第一个非空值:

select 
    c.corp_id, 
    c.parent_corp_id, 
    coalesce(c.col1, p.col1) col1, 
    coalesce(c.col2, p.col2) col2, 
    coalesce(c.col3, p.col3) col3 
from mytable c 
left join mytable p on p.corp_id = c.parent_corp_id 

获得“具有非空值的第一行”,添加:

where coalesce(c.col1, p.col1, c.col2, p.col2, c.col3, p.col3) is not null 
and rownum = 1 
+0

这对我不起作用我很害怕,我需要一个分层查询,因为我不知道有多少层次需要去找,直到找到一个值... – mlnyc 2014-09-20 14:39:49

+0

@mlnyc is there an上限的水平? – Bohemian 2014-09-20 15:53:14

0

您确实需要使用hiearchial查询(w/connect by子句),因为您有一个具有子项的父项,并且该子项是另一个子项的父项(尽管您的示例数据没有将其带入播放),但是要求您显示'first not null col1'和'first not null col2“等是与分层关系完全不同的问题。

请尝试以下操作,为了便于说明,我在小提琴中添加了一些其他示例数据(请检查左侧的DDL)。

它看起来像你期望的输出,你不想显示最高级别的父母,这就是为什么我把“where s.parent_corp_id不为空”在最后。如果你确实想要展示这些,请把这条线路拿出来。

否则,这将显示基于它们的组的col1/col2/col3值。请注意,示例2中的父级如何为高级父节点,其中4作为子节点,4也是8的父节点。因此,corp_id 8和4是同一分支的一部分,因此它们显示相同的col1/col2/col3值,根据您的要求,这些都是整个分支的第一个非空值。

小提琴:http://sqlfiddle.com/#!4/ef218/14/0

with sub as 
(select corp_id, 
     parent_corp_id, 
     col1, 
     col2, 
     col3, 
     level as lvl, 
     rownum - level as grp 
    from tbl 
    connect by prior corp_id = parent_corp_id 
    start with parent_corp_id is null), 
col1_lvl as 
(select grp, col1 
    from sub s 
    where s.lvl = (select min(x.lvl) 
        from sub x 
        where x.col1 is not null 
        and x.grp = s.grp)), 
col2_lvl as 
(select grp, col2 
    from sub s 
    where s.lvl = (select min(x.lvl) 
        from sub x 
        where x.col2 is not null 
        and x.grp = s.grp)), 
col3_lvl as 
(select grp, col3 
    from sub s 
    where s.lvl = (select min(x.lvl) 
        from sub x 
        where x.col3 is not null 
        and x.grp = s.grp)) 
select s.corp_id, s.parent_corp_id, c1.col1, c2.col2, c3.col3 
    from sub s 
    left join col1_lvl c1 
    on s.grp = c1.grp 
    left join col2_lvl c2 
    on s.grp = c2.grp 
    left join col3_lvl c3 
    on s.grp = c3.grp 
where s.parent_corp_id is not null 

如果不提供你基于我曾经请提供我在DDL中使用的数据的预期输出的样本数据预期输出小提琴。