Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何在Oracle 10g中解析相邻列表?_Sql_Oracle_Oracle10g_Hierarchy_Common Table Expression - Fatal编程技术网

Sql 如何在Oracle 10g中解析相邻列表?

Sql 如何在Oracle 10g中解析相邻列表?,sql,oracle,oracle10g,hierarchy,common-table-expression,Sql,Oracle,Oracle10g,Hierarchy,Common Table Expression,我有一张这样的桌子: +---------+--------+ | EMP_ID | MGR_iD | +---------+--------+ | 1 | 1 | | 2 | 1 | | 3 | 1 | | 4 | 2 | | 5 | 2 | | 6 | 2 | | 7 | 3 | | 8 | 5 | |

我有一张这样的桌子:

+---------+--------+
| EMP_ID  | MGR_iD |
+---------+--------+
|       1 |      1 |
|       2 |      1 |
|       3 |      1 |
|       4 |      2 |
|       5 |      2 |
|       6 |      2 |
|       7 |      3 |
|       8 |      5 |
|       9 |      7 |
|      10 |      5 |
|      11 |      7 |
|      12 |      9 |
|      13 |      9 |
|      14 |      9 |
+---------+--------+
我正在尝试解析此相邻列表以生成以下结果集:

| EMP_ID | MGR_ID | LV | LEVEL1 | LEVEL2 | LEVEL3 | LEVEL4 | LEVEL5 |
---------------------------------------------------------------------
|      1 |      1 |  1 |      1 |      1 |      1 |      1 |      1 |
|      2 |      1 |  2 |      1 |      2 |      2 |      2 |      2 |
|      3 |      1 |  2 |      1 |      3 |      3 |      3 |      3 |
|      4 |      2 |  3 |      1 |      2 |      4 |      4 |      4 |
|      5 |      2 |  3 |      1 |      2 |      5 |      5 |      5 |
|      6 |      2 |  3 |      1 |      2 |      6 |      6 |      6 |
|      7 |      3 |  3 |      1 |      3 |      7 |      7 |      7 |
|      8 |      5 |  4 |      1 |      2 |      5 |      8 |      8 |
|      9 |      7 |  4 |      1 |      3 |      7 |      9 |      9 |
|     10 |      5 |  4 |      1 |      2 |      5 |     10 |     10 |
|     11 |      7 |  4 |      1 |      3 |      7 |     11 |     11 |
|     12 |      9 |  5 |      1 |      3 |      7 |      9 |     12 |
|     13 |      9 |  5 |      1 |      3 |      7 |      9 |     13 |
|     14 |      9 |  5 |      1 |      3 |      7 |      9 |     14 |
以下是我迄今为止所取得的成就:

create table PC (
EMP_ID NUMBER NULL,
MGR_ID NUMBER NULL
);

INSERT INTO PC (EMP_ID, MGR_ID) 
VALUES (1.0, 1.0);

INSERT INTO PC (EMP_ID, MGR_ID) 
VALUES (2.0, 1.0);

INSERT INTO PC (EMP_ID, MGR_ID) 
VALUES (3.0, 1.0);

INSERT INTO PC (EMP_ID, MGR_ID) 
VALUES (4.0, 2.0);

INSERT INTO PC (EMP_ID, MGR_ID) 
VALUES (5.0, 2.0);

INSERT INTO PC (EMP_ID, MGR_ID) 
VALUES (6.0, 2.0);

INSERT INTO PC (EMP_ID, MGR_ID) 
VALUES (7.0, 3.0);

INSERT INTO PC (EMP_ID, MGR_ID) 
VALUES (8.0, 5.0);

INSERT INTO PC (EMP_ID, MGR_ID) 
VALUES (9.0, 7.0);

INSERT INTO PC (EMP_ID, MGR_ID) 
VALUES (10.0, 5.0);

INSERT INTO PC (EMP_ID, MGR_ID) 
VALUES (11.0, 7.0);

INSERT INTO PC (EMP_ID, MGR_ID) 
VALUES (12.0, 9.0);

INSERT INTO PC (EMP_ID, MGR_ID) 
VALUES (13.0, 9.0);

INSERT INTO PC (EMP_ID, MGR_ID) 
VALUES (14.0, 9.0);
以及查询:

 WITH PERSON_HIER AS 
(
SELECT  1 as level1, 
        CAST(NULL AS NUMBER) as level2,
        CAST(NULL AS NUMBER) as level3,
        CAST(NULL AS NUMBER) as level4,
        CAST(NULL AS NUMBER) as level5
FROM    PC
WHERE EMP_ID = 1 AND MGR_ID = 1
UNION ALL
SELECT  L1.EMP_ID AS LEVEL1,
        L2.EMP_ID AS LEVEL2,
        L3.EMP_ID AS LEVEL3,
        L4.EMP_ID AS LEVEL4,
        L5.EMP_ID AS LEVEL5
FROM PC L1
  LEFT OUTER JOIN PC L2 ON (L1.EMP_ID = L2.MGR_ID AND L2.EMP_ID != L1.EMP_ID)
  LEFT OUTER JOIN PC L3 ON (L2.EMP_ID = L3.MGR_ID)
  LEFT OUTER JOIN PC L4 ON (L3.EMP_ID = L4.MGR_ID)
  LEFT OUTER JOIN PC L5 ON (L4.EMP_ID = L5.MGR_ID)
WHERE L1.MGR_ID = L1.EMP_ID
)
SELECT  level1,
        coalesce(level2, level1) AS LEVEL2,
        coalesce(level3, level2, level1) AS LEVEL3,
        coalesce(level4, level3, level2, level1) AS LEVEL4,
        coalesce(level5, level4, level3, level2, level1) AS LEVEL5              
FROM PERSON_HIER 
order by level5 

我使用的是Oracle 10g,因此在Oracle 10g中不可能使用递归CTE或层次查询。您可以使用以下单个层次查询:


.

现在,一个改进的版本显示了正确的层次结构:

select emp_id, mgr_id, lvl, h, 
   nvl(substr(h,instr(h,'/',1, 2)+1, instr(h, '/',1, 3)- instr(h,'/',1,2)-1), emp_id) as lvl1,
   nvl(substr(h,instr(h,'/',1, 3)+1, instr(h, '/',1, 4)- instr(h,'/',1,3)-1), emp_id) as lvl2,
   nvl(substr(h,instr(h,'/',1, 4)+1, instr(h, '/',1, 5)- instr(h,'/',1,4)-1), emp_id) as lvl3,
   nvl(substr(h,instr(h,'/',1, 5)+1, instr(h, '/',1, 6) -instr(h,'/',1,5)-1), emp_id) as lvl4,
   nvl(substr(h,instr(h,'/',1, 6)+1, instr(h, '/',1, 7) -instr(h,'/',1,6)-1), emp_id) as lvl5

from(
select emp_id, mgr_id , level lvl, sys_connect_by_path(mgr_id, '/')||'/' h
from pc
connect by nocycle prior emp_id = mgr_id 
start with emp_id = 1 
)
order by emp_id;

EMP_ID  MGR_ID  LVL H               LVL1    LVL2    LVL3    LVL4    LVL5
2           1   1   1/1/               1    2   2   2   2
3           1   1   1/1/               1    3   3   3   3
4           2   2   2/1/2/             1    2   4   4   4
5           2   2   2/1/2/             1    2   5   5   5
6           2   2   2/1/2/             1    2   6   6   6
7           3   2   3/1/3/             1    3   7   7   7
8           5   3   5/1/2/5/           1    2   5   8   8
9           7   3   7/1/3/7/           1    3   7   9   9
10          5   3   5/1/2/5/           1    2   5   10  10
11          7   3   7/1/3/7/           1    3   7   11  11
12          9   4   9/1/3/7/9/         1    3   7   9   12
13          9   4   9/1/3/7/9/         1    3   7   9   13
14          9   4   9/1/3/7/9/         1    3   7   9   14
15         14   5   14/1/3/7/9/14/     1    3   7   9   14
这是我第一次尝试:

select emp_id, mgr_id, lvl, h,
   nvl(substr(h,instr(h,' ',1, 1), instr(h, ' ',1, 2)- instr(h,' ',1,1)), emp_id) as lvl1,
   nvl(substr(h,instr(h,' ',1, 2), instr(h, ' ',1, 3)- instr(h,' ',1,2)), emp_id) as lvl2,
   nvl(substr(h,instr(h,' ',1, 3), instr(h, ' ',1, 4)- instr(h,' ',1,3)), emp_id) as lvl3,
   nvl(substr(h,instr(h,' ',1, 4), instr(h, ' ',1, 5)- instr(h,' ',1,4)), emp_id) as lvl4,
   nvl(substr(h,instr(h,' ',1, 5), instr(h, ' ',1, 6) -instr(h,' ',1,5)), emp_id) as lvl5

from(
select emp_id, mgr_id , level lvl, sys_connect_by_path(mgr_id, ' ') h
from pc
connect by nocycle prior emp_id = mgr_id 
start with emp_id = 1 
)
order by emp_id;

根据您的需求添加联合

17:33:45 HR@oars_sandbox> ed
Wrote file S:\tools\buffer.sql

  1  select emp_id,
  2         mgr_id,
  3         lvl,
  4         path,
  5         replace(regexp_substr(path, '#[0-9]+', 1, 1), '#') l1,
  6         replace(regexp_substr(path, '#[0-9]+', 1, 2), '#') l2,
  7         replace(regexp_substr(path, '#[0-9]+', 1, 3), '#') l3,
  8         replace(regexp_substr(path, '#[0-9]+', 1, 4), '#') l4,
  9         replace(regexp_substr(path, '#[0-9]+', 1, 5), '#') l5
 10    from (
 11  select emp_id, mgr_id, level lvl, sys_connect_by_path(emp_id, '#') path
 12    from pc
 13   connect by mgr_id = prior emp_id and level <= 5 and mgr_id <> emp_id
 14   start with emp_id = 1
 15  order by 3,1
 16* )
17:34:29 HR@oars_sandbox> /

    EMP_ID     MGR_ID        LVL PATH                 L1    L2    L3    L4    L5
---------- ---------- ---------- -------------------- ----- ----- ----- ----- -----
         1          1          1 #1                   1
         2          1          2 #1#2                 1     2
         3          1          2 #1#3                 1     3
         4          2          3 #1#2#4               1     2     4
         5          2          3 #1#2#5               1     2     5
         6          2          3 #1#2#6               1     2     6
         7          3          3 #1#3#7               1     3     7
         8          5          4 #1#2#5#8             1     2     5     8
         9          7          4 #1#3#7#9             1     3     7     9
        10          5          4 #1#2#5#10            1     2     5     10
        11          7          4 #1#3#7#11            1     3     7     11
        12          9          5 #1#3#7#9#12          1     3     7     9     12
        13          9          5 #1#3#7#9#13          1     3     7     9     13
        14          9          5 #1#3#7#9#14          1     3     7     9     14

14 rows selected.

Elapsed: 00:00:00.03
17:34:32 HR@oars_sandbox>

如果有超过5个级别,会发生什么?我只想输出前5个级别…什么意思,在10g中不可能进行分层查询?连接方式适用于不同的年龄段,为什么要坚持使用CTE?请参见例如此链接:。如果你能帮我连接,我会很高兴的。这是层次结构的深度。很好的想法从我这里获得所有祖先+1@然后它只返回一行,因为子查询只在根上生成emp_id 14。因此子查询似乎不起作用。它在11g XE上运行良好。谢谢,但这似乎会在结果集中产生重复的emp_id:s。哎哟,在改进的版本中,我删除了记录1,1是多余的。我已经纠正了这一点,这是为了测试目的。见
17:33:45 HR@oars_sandbox> ed
Wrote file S:\tools\buffer.sql

  1  select emp_id,
  2         mgr_id,
  3         lvl,
  4         path,
  5         replace(regexp_substr(path, '#[0-9]+', 1, 1), '#') l1,
  6         replace(regexp_substr(path, '#[0-9]+', 1, 2), '#') l2,
  7         replace(regexp_substr(path, '#[0-9]+', 1, 3), '#') l3,
  8         replace(regexp_substr(path, '#[0-9]+', 1, 4), '#') l4,
  9         replace(regexp_substr(path, '#[0-9]+', 1, 5), '#') l5
 10    from (
 11  select emp_id, mgr_id, level lvl, sys_connect_by_path(emp_id, '#') path
 12    from pc
 13   connect by mgr_id = prior emp_id and level <= 5 and mgr_id <> emp_id
 14   start with emp_id = 1
 15  order by 3,1
 16* )
17:34:29 HR@oars_sandbox> /

    EMP_ID     MGR_ID        LVL PATH                 L1    L2    L3    L4    L5
---------- ---------- ---------- -------------------- ----- ----- ----- ----- -----
         1          1          1 #1                   1
         2          1          2 #1#2                 1     2
         3          1          2 #1#3                 1     3
         4          2          3 #1#2#4               1     2     4
         5          2          3 #1#2#5               1     2     5
         6          2          3 #1#2#6               1     2     6
         7          3          3 #1#3#7               1     3     7
         8          5          4 #1#2#5#8             1     2     5     8
         9          7          4 #1#3#7#9             1     3     7     9
        10          5          4 #1#2#5#10            1     2     5     10
        11          7          4 #1#3#7#11            1     3     7     11
        12          9          5 #1#3#7#9#12          1     3     7     9     12
        13          9          5 #1#3#7#9#13          1     3     7     9     13
        14          9          5 #1#3#7#9#14          1     3     7     9     14

14 rows selected.

Elapsed: 00:00:00.03
17:34:32 HR@oars_sandbox>