从表中取消转动数据

时间:2015-06-17 22:30:16

标签: sql database oracle

我需要在VIEW或Materialized VIEW等表结构中优化下面的数据。请帮忙说明如何实现它。

Employee  Manager  Management_Chain 
vp2221    bg7915   jd613hbs0712sm2389mw6143mc7580ab3793bg7915vp2221
bg7915    ab3793   jd613hbs0712sm2389mw6143mc7580ab3793bg7915
ab3793    mc7580   jd613hbs0712sm2389mw6143mc7580ab3793
rx2131    bg7915   jd613hbs0712sm2389mw6143mc7580ab3793bg7915rx2131

要求是将上述数据转换如下...根据Employee和Management_Chain列添加距离列值(0,1,2,3,4,....)。对于每个员工,都有一个管理链,其中员工ID也是管理链的一部分。

Employee     Manager   Distance   
vp2221       vp2221      0    
vp2221       bg7915      1    
vp2221       ab3793      2    
vp2221       mc7580      3   
vp2221       mw6143      4  
vp2221       sm2389      5    
vp2221       bs0712      6    
vp2221       jd613h      7    
bg7915       bg7915      0    
bg7915       ab3793      1   
bg7915       mc7580      2   
bg7915       mw6143      3   
bg7915       sm2389      4    
bg7915       bs0712      5    
bg7915       jd613h      6    
ab3793       ab3793      0   
ab3793       mc7580      1    
ab3793       mw6143      2    
ab3793       sm2389      3    
ab3793       bs0712      4    
ab3793       jd613h      5    
rx2131       vp2221      0   
rx2131       bg7915      1   
rx2131       ab3793      2    
rx2131       mc7580      3    
rx2131       mw6143      4    
rx2131       sm2389      5   
rx2131       bs0712      6    
rx2131       jd613h      7    
....

2 个答案:

答案 0 :(得分:0)

您可以使用unpivot执行此操作 -

select employee, val as manager, min_n as distance
from(
select employee,
       manager,
       case when length(management_chain)/6 >= 1 then substr(management_chain, length(management_chain) - 5, 6) end as min_00,
       case when length(management_chain)/6 >= 2 then substr(management_chain, length(management_chain) - 11, 6) end as min_01,
       case when length(management_chain)/6 >= 3 then substr(management_chain, length(management_chain) - 17, 6) end as min_02,
       case when length(management_chain)/6 >= 4 then substr(management_chain, length(management_chain) - 23, 6) end as min_03,
       case when length(management_chain)/6 >= 5 then substr(management_chain, length(management_chain) - 29, 6) end as min_04,
       case when length(management_chain)/6 >= 6 then substr(management_chain, length(management_chain) - 35, 6) end as min_05,
       case when length(management_chain)/6 >= 7 then substr(management_chain, length(management_chain) - 41, 6) end as min_06,
       case when length(management_chain)/6 >= 8 then substr(management_chain, length(management_chain) - 47, 6) end as min_07,
       case when length(management_chain)/6 >= 9 then substr(management_chain, length(management_chain) - 53, 6) end as min_08,
       case when length(management_chain)/6 >= 10 then substr(management_chain, length(management_chain) - 59, 6) end as min_09
  from tbl
) unpivot (
 val for (min_n) in
 (
   min_00 as 0,
    min_01 as 1,
     min_02 as 2,
      min_03 as 3,
       min_04 as 4,
        min_05 as 5,
         min_06 as 6,
          min_07 as 7,
           min_08 as 8,
            min_09 as 9
 )
);

小提琴: http://sqlfiddle.com/#!4/99cc5/3/0

如果management_chain总是有10名或更少的员工,则上述工作将有效。如果可能还有更多,则需要根据需要添加其他行。如果有更少,这不是问题,正如您在演示中看到的那样,默认情况下,unpivot不包含空值(并且内联视图中的case语句确保在这些情况下使用空值)。

答案 1 :(得分:0)

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE NEEDS_REFACTORING ( Employee,  Manager,  Management_Chain ) AS
          SELECT 'vp2221','bg7915','jd613hbs0712sm2389mw6143mc7580ab3793bg7915vp2221' FROM DUAL
UNION ALL SELECT 'bg7915','ab3793','jd613hbs0712sm2389mw6143mc7580ab3793bg7915' FROM DUAL
UNION ALL SELECT 'ab3793','mc7580','jd613hbs0712sm2389mw6143mc7580ab3793' FROM DUAL
UNION ALL SELECT 'rx2131','bg7915','jd613hbs0712sm2389mw6143mc7580ab3793bg7915rx2131' FROM DUAL;

查询1

SELECT EMPLOYEE,
       SUBSTR( MANAGEMENT_CHAIN, 6*COLUMN_VALUE - 5, 6 ) AS MANAGER,
       LENGTH(MANAGEMENT_CHAIN)/6 - COLUMN_VALUE AS DISTANCE
FROM   NEEDS_REFACTORING r,
       TABLE(
         CAST(
           MULTISET(
             SELECT LEVEL
             FROM   DUAL
             CONNECT BY 6*LEVEL <= LENGTH( r.MANAGEMENT_CHAIN )
           )
           AS SYS.ODCINUMBERLIST
         )
       )
ORDER BY 1,3

<强> Results

| EMPLOYEE | MANAGER | DISTANCE |
|----------|---------|----------|
|   ab3793 |  ab3793 |        0 |
|   ab3793 |  mc7580 |        1 |
|   ab3793 |  mw6143 |        2 |
|   ab3793 |  sm2389 |        3 |
|   ab3793 |  bs0712 |        4 |
|   ab3793 |  jd613h |        5 |
|   bg7915 |  bg7915 |        0 |
|   bg7915 |  ab3793 |        1 |
|   bg7915 |  mc7580 |        2 |
|   bg7915 |  mw6143 |        3 |
|   bg7915 |  sm2389 |        4 |
|   bg7915 |  bs0712 |        5 |
|   bg7915 |  jd613h |        6 |
|   rx2131 |  rx2131 |        0 |
|   rx2131 |  bg7915 |        1 |
|   rx2131 |  ab3793 |        2 |
|   rx2131 |  mc7580 |        3 |
|   rx2131 |  mw6143 |        4 |
|   rx2131 |  sm2389 |        5 |
|   rx2131 |  bs0712 |        6 |
|   rx2131 |  jd613h |        7 |
|   vp2221 |  vp2221 |        0 |
|   vp2221 |  bg7915 |        1 |
|   vp2221 |  ab3793 |        2 |
|   vp2221 |  mc7580 |        3 |
|   vp2221 |  mw6143 |        4 |
|   vp2221 |  sm2389 |        5 |
|   vp2221 |  bs0712 |        6 |
|   vp2221 |  jd613h |        7 |