如果子层数据在Oracle分层表中为空,则获取父数据

时间:2014-09-20 14:31:35

标签: sql oracle hierarchy connect-by

在Oracle 10g中,我有以下分层表:

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个级别来研究。

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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

你确实需要使用一个层次结构查询(带有connect by子句),因为你有一个带有子节点的父节点,并且该子节点是另一个子节点的父节点(尽管你的示例数据没有带来然而,要求你显示'first not null col1'和'first not null col2'等是完全不同于分层关系的问题。

尝试以下操作,我向小提琴添加了一些额外的样本数据(请查看左侧的DDL)以用于说明目的。

在您的预期输出中,您似乎不想显示最高级别的父级,这就是为什么我在结尾处放置“where s.parent_corp_id不为空”的原因。如果你确实想要展示那些,那就拿出那条线。

否则,这将显示基于其组的col1 / col2 / col3值。请注意,示例2中的高级父级是4,子级是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

如果根据我使用的样本数据没有提供您期望的输出,请提供我在小提琴上使用的数据的预期输出。