拆散分层数据

时间:2015-02-12 05:49:04

标签: sql oracle

我有一个包含分层数据的表,例如:

    LEVEL   id_value    parent_id_value     description 
0   1       505         None                Top Hierarchy
1   2       1000        505                 Sub Hierarchy
2   2       300         505                 Other Sub Hierarchy
3   3       0040        300                 Rookie hierarchy
4   3       0042        300                 Bottom level

我需要的是一个查询,它会给我这个:

0   id_value        3                   2                   1
1         40        Rookie hierarchy    Other Sub Hierarchy Top Hierarchy
2         42        Bottom level        Other Sub Hierarchy Top Hierarchy
3       1000        NULL                Sub Hierarchy       Top Hierarchy

看起来它应该很简单,但我遗漏了一些东西......

3 个答案:

答案 0 :(得分:1)

我已将您的示例数据要求转换为SQL查询。请注意:

  • 此行程一次又一次地将表连接到自身
  • 必须在每个联接上使用表别名。
  • 您可以调整此查询以符合您的一般要求。
  • 要匹配您的数据样本,第二次加入是左连接

这是:

select 
  coalesce( l3.id_value,l2.id_value) as id_value ,
  l3.description as "3",
  l2.description as "2",
  l1.description as "1"
from t l1 inner join
     t l2 on l2."LEVEL"=2 and l1.id_value = l2.parent_id_value
          left outer join
     t l3 on l3."LEVEL"=3 and l2.id_value = l3.parent_id_value
where l1.LEVEL = 1

Check it on sqlFiddle

答案 1 :(得分:0)

此查询提供了所有需要的信息:

select id_value, --parent_id_value piv, description, level tlvl, 
    sys_connect_by_path(description, '/') tpath
  from hd where connect_by_isleaf = 1
  start with parent_id_value not in (select id_value from hd)
  connect by parent_id_value = prior id_value

结果

id_value  tpath
--------  ---------------------------------------------------------------
      40  /Top hierarchy/Other sub hierarchy/Rookie hierarchy    
      42  /Top hierarchy/Other sub hierarchy/Bottom level        
    1000  /Top hierarchy/Sub hierarchy

现在,如果我们假设最大层次结构深度为3,那么此查询将子层次结构放在不同的列中。

with leaves as (
  select id_value, parent_id_value piv, description, level tlvl, 
      sys_connect_by_path(rpad(description, 20), '/') tpath
    from hd where connect_by_isleaf = 1
    start with parent_id_value not in (select id_value from hd)
    connect by parent_id_value = prior id_value )
select id_value, 
    substr(tpath, 2*20 + 4, 20) l3, 
    substr(tpath, 1*20 + 3, 20) l2,
    substr(tpath, 0*20 + 2, 20) l1
  from leaves

=====================================================================
id_value  L3                    L2                      L1 
      40  Rookie hierarchy      Other sub hierarchy     Top hierarchy       
      42  Bottom level          Other sub hierarchy     Top hierarchy       
    1000                        Sub hierarchy           Top hierarchy       

如果描述长度> 20将此值更改为字段列长度。

这也可以在PL / SQL中动态地完成,例如首先计算深度,通过execute immediate创建具有适当列数的表,并将层次结构放入右列。

答案 2 :(得分:-1)

不确定为什么需要LEVEL列,但简单的分层查询应该有效。如果有固定数量的级别,只需将CONNECT_BY_PATH拆分为多个列:

-- sample table
CREATE TABLE TT1
 (ID_VALUE          NUMBER,
  PARENT_ID_VALUE   NUMBER,
  DESCRIPTION       VARCHAR2(32));

-- the query itself
 SELECT ID_VALUE,
        REGEXP_SUBSTR(SYS_CONNECT_BY_PATH(DESCRIPTION, '/'),  '[^/]+', 1, 3) L3,
        REGEXP_SUBSTR(SYS_CONNECT_BY_PATH(DESCRIPTION, '/'),  '[^/]+', 1, 2) L2,
        REGEXP_SUBSTR(SYS_CONNECT_BY_PATH(DESCRIPTION, '/'),  '[^/]+', 1, 1) L1
   FROM TT1
  WHERE CONNECT_BY_ISLEAF = 1
  START WITH PARENT_ID_VALUE IS NULL
CONNECT BY PARENT_ID_VALUE = PRIOR ID_VALUE