使用Oracle函数创建层次结构

时间:2016-02-01 11:40:21

标签: oracle plsql hierarchical-data

是否可以使用oracle函数为维度创建层次结构?

请参阅下面的示例了解组织级别层次结构。

+-----+------+---------+
| EMP | LEAD | MANAGER |
+-----+------+---------+
| E1  | L1   | M1      |
| E3  | L3   | M1      |
| E2  | L2   | M1      |
+-----+------+---------+

但数据的最终表示应该是( sample ):

+-----+----------+----------+----------+
| EMP | LVL_1_ID | LVL_2_ID | LVL_3_ID |
+-----+----------+----------+----------+
| M1  |          |          | M1       |
| L1  |          | L1       | M1       |
| L2  |          | L2       | M1       |
| E1  | E1       | L1       | M1       |
| E2  | E2       | L2       | M1       |
| E3  | E3       | L3       | M1       |
| L3  |          | L3       | M1       |
+-----+----------+----------+----------+

EMP_ID列将包含所有员工的条目(包括潜在客户和经理)。

代码:

    SELECT employee AS emp_id,
    employee AS Level_1_id,
    LEAD AS level_2_id,
    Manager AS Level_3_id
    FROM temp_emp
    UNION
    SELECT LEAD AS emp_id,
    NULL AS Level_1_id,
    LEAD AS level_2_id,
    Manager AS Level_3_id
    FROM temp_emp
    UNION
    SELECT manager AS emp_id,
    NULL AS Level_1_id,
    NULL AS level_2_id,
    Manager AS Level_3_id
    FROM temp_emp ;

根据评论,我在以下数据集中尝试了“Connect By”子句:

+-----+---------+
| EMP | MANAGER |
+-----+---------+
| E1  | L1      |
| E2  | L1      |
| E3  | L2      |
| L1  | M1      |
| L2  | M1      |
| M1  |         |
+-----+---------+

获得以下结果:

 +-----+----------+----------+-----------+
 | EMP | LVL_1_ID | LVL_2_ID | LVL_3_ID  |
 +-----+----------+----------+-----------+
 | M1   |          |          |M1        |
 | L1   |          |L1        |          |
 | L2   |          |L2        |          |
 | E1   |E1        |          |          |
 | E2   |E2        |          |          |
 | E3   |E3        |          |          |
 +-----+----------+----------+-----------+

用于获取此代码的代码(仍然不是必需的答案):

SELECT * FROM (
SELECT EMP AS CH,EMP AS emp,LEVEL AS LVL
FROM TEMP_EMP
START WITH MANAGER IS NULL
CONNECT BY  PRIOR EMP = MANAGER)
PIVOT (MAX(CH) FOR (LVL) IN ('3' AS LVL_1_ID,'2' AS LVL_2_ID,'1' AS  LVL_3_ID));

预期结果:

+-----+----------+----------+----------+
| EMP | LVL_1_ID | LVL_2_ID | LVL_3_ID |
+-----+----------+----------+----------+
| M1  |          |          | M1       |
| L1  |          | L1       | M1       |
| L2  |          | L2       | M1       |
| E1  | E1       | L1       | M1       |
| E2  | E2       | L1       | M1       |
| E3  | E3       | L2       | M1       |
+-----+----------+----------+----------+

3 个答案:

答案 0 :(得分:1)

以下代码将提供所需答案:

select ch AS EMP,lvl,
REGEXP_SUBSTR (path, '[^///]+', 1, 3)   as lvl1,
REGEXP_SUBSTR (path, '[^///]+', 1, 2)   as lvl2,
REGEXP_SUBSTR (path, '[^///]+', 1, 1)   as lvl3
from (
SELECT EMP AS CH,manager as par,level as lvl,
SYS_CONNECT_BY_PATH(EMP , '///') as path
FROM TEMP_EMP
START WITH MANAGER IS NULL
CONNECT BY  PRIOR EMP = MANAGER);

答案 1 :(得分:0)

Oracle 通过连接,并且它具有伪列级别,可帮助您跟踪层次结构中的位置

Hierarchical Queries - Oracle Documentation

一个很好的解释:http://www.adp-gmbh.ch/ora/sql/connect_by.html

答案 2 :(得分:0)

使用以下查询来避免UNION,

select ch AS EMP,lvl,
REGEXP_SUBSTR (path, '[^///]+', 1, 3)   as lvl1,
REGEXP_SUBSTR (path, '[^///]+', 1, 2)   as lvl2,
REGEXP_SUBSTR (path, '[^///]+', 1, 1)   as lvl3
from (
SELECT EMP AS CH,manager as par,level as lvl,
SYS_CONNECT_BY_PATH(EMP , '///') as path
FROM (select emp,lead(emp,1,NULL) over(partition by r order by lvls) manager from (  
select val emp,lvls,r from (
select R,lvls,val from (
SELECT emp,lead,manager,row_number()over(order by emp) r FROM TEMP_EMP2)   unpivot(val for lvls in (emp as '1', lead as '2',manager as '3') ))))
START WITH MANAGER IS NULL
CONNECT BY  PRIOR EMP = MANAGER);