Oracle Hierarchical Query将不同的级别分成不同的列

时间:2017-04-28 19:20:14

标签: oracle

我的源数据就像这样

Childid | Parent ID
------- | ---------
1 | NULL
2 | 1
3 | 1
4 | 2
5 | 4
6 | 5
7 | 6

我需要一个oracle查询来显示这样的输出。

Child | L1Parent | l2Parent | L3Parent | L4Parent | L5Parent
----- | -------- | -------- | -------- | -------- | --------
1 | NULL
2 | 1
3 | 1
4 | 1 | 2
5 | 1 | 2 | 4
6 | 1 | 2 | 4 | 5
7 | 1 | 2 | 4 | 5 | 6

2 个答案:

答案 0 :(得分:1)

这对我来说更容易:

SELECT childId,
       trim(SYS_CONNECT_BY_PATH(decode(level,2,parentId,''), ' ')) AS L1,
       trim(SYS_CONNECT_BY_PATH(decode(level,3,parentId,''), ' ')) AS L2,
       trim(SYS_CONNECT_BY_PATH(decode(level,4,parentId,''), ' ')) AS L3,
       trim(SYS_CONNECT_BY_PATH(decode(level,5,parentId,''), ' ')) AS L4,
       trim(SYS_CONNECT_BY_PATH(decode(level,6,parentId,''), ' ')) AS L5,
       trim(SYS_CONNECT_BY_PATH(decode(level,7,parentId,''), ' ')) AS L6,
       trim(SYS_CONNECT_BY_PATH(decode(level,8,parentId,''), ' ')) AS L7
FROM table_name
START WITH parentId is null
CONNECT BY PRIOR childId = parentId;

答案 1 :(得分:0)

Oracle安装程序

CREATE TABLE table_name ( childId, parentId ) AS
  SELECT 1, NULL FROM DUAL UNION ALL
  SELECT 2, 1    FROM DUAL UNION ALL
  SELECT 3, 1    FROM DUAL UNION ALL
  SELECT 4, 2    FROM DUAL UNION ALL
  SELECT 5, 4    FROM DUAL UNION ALL
  SELECT 6, 5    FROM DUAL UNION ALL
  SELECT 7, 6    FROM DUAL;

<强>查询

SELECT childId,
       CASE WHEN p02 = 1 THEN NULL WHEN p03 = 1 THEN SUBSTR( path, p02 ) ELSE SUBSTR( path, p02, p03 - p02 - 1 ) END AS Lp1,
       CASE WHEN p03 = 1 THEN NULL WHEN p04 = 1 THEN SUBSTR( path, p03 ) ELSE SUBSTR( path, p03, p04 - p03 - 1 ) END AS lp2,
       CASE WHEN p04 = 1 THEN NULL WHEN p05 = 1 THEN SUBSTR( path, p04 ) ELSE SUBSTR( path, p04, p05 - p04 - 1 ) END AS lp3,
       CASE WHEN p05 = 1 THEN NULL WHEN p06 = 1 THEN SUBSTR( path, p05 ) ELSE SUBSTR( path, p05, p06 - p05 - 1 ) END AS lp4,
       CASE WHEN p06 = 1 THEN NULL WHEN p07 = 1 THEN SUBSTR( path, p06 ) ELSE SUBSTR( path, p06, p07 - p06 - 1 ) END AS lp5,
       CASE WHEN p07 = 1 THEN NULL WHEN p08 = 1 THEN SUBSTR( path, p07 ) ELSE SUBSTR( path, p07, p08 - p07 - 1 ) END AS lp6
FROM   (
  SELECT childId,
         path,
         INSTR( path, '/', 1,  2 ) + 1 AS p02,
         INSTR( path, '/', 1,  3 ) + 1 AS p03,
         INSTR( path, '/', 1,  4 ) + 1 AS p04,
         INSTR( path, '/', 1,  5 ) + 1 AS p05,
         INSTR( path, '/', 1,  6 ) + 1 AS p06,
         INSTR( path, '/', 1,  7 ) + 1 AS p07,
         INSTR( path, '/', 1,  8 ) + 1 AS p08
  FROM   (
    SELECT childId,
           SYS_CONNECT_BY_PATH( parentId, '/') AS path
    FROM   table_name
    START WITH parentId IS NULL
    CONNECT BY PRIOR childId = parentId
  )
);

<强>输出

   CHILDID LP1 LP2 LP3 LP4 LP5 LP6
---------- --- --- --- --- --- ---
         1                        
         2 1                      
         4 1   2                  
         5 1   2   4              
         6 1   2   4   5          
         7 1   2   4   5   6      
         3 1                      

查询2 - 正则表达式

SELECT childId,
       TO_NUMBER( REGEXP_SUBSTR( path, '/([^/]*)', 1, 2, NULL, 1 ) ) AS lp1,
       TO_NUMBER( REGEXP_SUBSTR( path, '/([^/]*)', 1, 3, NULL, 1 ) ) AS lp2,
       TO_NUMBER( REGEXP_SUBSTR( path, '/([^/]*)', 1, 4, NULL, 1 ) ) AS lp3,
       TO_NUMBER( REGEXP_SUBSTR( path, '/([^/]*)', 1, 5, NULL, 1 ) ) AS lp4,
       TO_NUMBER( REGEXP_SUBSTR( path, '/([^/]*)', 1, 6, NULL, 1 ) ) AS lp5,
       TO_NUMBER( REGEXP_SUBSTR( path, '/([^/]*)', 1, 7, NULL, 1 ) ) AS lp6,
       TO_NUMBER( REGEXP_SUBSTR( path, '/([^/]*)', 1, 8, NULL, 1 ) ) AS lp7
FROM   (
  SELECT childId,
         SYS_CONNECT_BY_PATH( parentId, '/') AS path
  FROM   table_name
  START WITH parentId IS NULL
  CONNECT BY PRIOR childId = parentId
);