我有一个具有以下部门结构的Oracle表:
cddepartment - NUMBER - unique numeric identifier for department
iddepartment - VARCHAR - unique string identifier for department
nmdepartment - VARCHAR - name of department
cddeptowner - NUMBER - numeric identifier of department's parent (higher level)
部门的名字树,以视觉形式,看起来像这样:
DIRECCIÓN 1
----GERENCIA 1
--------SUBGERENCIA 1
------------JEFATURA 1
DIRECCION 2
----GERENCIA 2
--------SUBGERENCIA 2
------------JEFATURA 2
GERENCIA 3
----SUBGERENCIA 3
--------JEFATURA 3
GERENCIA 4
----SUBGERENCIA 4
DIRECCIÓN 5
----SUBGERENCIA 5
--------JEFATURA 5
...
...
DIRECCIÓN N
----GERENCIA N
--------SUBGERENCIA N
------------JEFATURA N
所有子树不一定具有相同的确切结构。其中一些可以是DIRECCION-GERENCIA-SUBGERENCIA-JEFATURA。其中一些可能是GERENCIA-SUBGERENCIA-JEFATURA,一些DIRECCION-SUBGERENCIA-JEFATURA,以及四种基本单元的近10种不同组合:DIRECCIÓN,GERENCIA,SUBGERENCIA和JEFATURA。
子树上下文中唯一固定的规则是DIRECCION总是处于比GERENCIA更高的级别,GERENCIA的级别高于SUBGERENCIA,而SUBGERENCIA的级别高于JEFATURA。子树可以由两个,三个或四个基本单元组成。
所以,我需要创建一个包含五个固定列的视图(在Oracle中),如下图所示。目标是从SQL报告中轻松查询部门的DIRECCION,GERENCIA,SUBGERENCIA和/或JEFATURA。
DEPARTMENT----DIRECCION----GERENCIA----SUBGERENCIA----JEFATURA
--------------------------------------------------------------------------
JEFATURA 1 DIRECCIÓN 1 GERENCIA 1 SUBGERENCIA 1 JEFATURA 1
SUBGERENCIA 1 DIRECCIÓN 1 GERENCIA 1 SUBGERENCIA 1
GERENCIA 1 DIRECCIÓN 1 GERENCIA 1
DIRECCIÓN 1 DIRECCIÓN 1
JEFATURA 2 DIRECCIÓN 2 GERENCIA 2 SUBGERENCIA 2 JEFATURA 2
SUBGERENCIA 2 DIRECCIÓN 2 GERENCIA 2 SUBGERENCIA 2
GERENCIA 2 DIRECCIÓN 2 GERENCIA 2
DIRECCIÓN 2 DIRECCIÓN 2
JEFATURA 3 GERENCIA 3 SUBGERENCIA 3 JEFATURA 3
SUBGERENCIA 3 GERENCIA 3 SUBGERENCIA 3
GERENCIA 3 GERENCIA 3
SUBGERENCIA 4 GERENCIA 4 SUBGERENCIA 4
GERENCIA 4 GERENCIA 4
JEFATURA 5 DIRECCIÓN 5 SUBGERENCIA 5 JEFATURA 5
SUBGERENCIA5 DIRECCIÓN 5 SUBGERENCIA 5
DIRECCIÓN 5 DIRECCIÓN 5
...
...
JEFATURA N DIRECCIÓN N GERENCIA N SUBGERENCIA N JEFATURA N
SUBGERENCIA N DIRECCIÓN N GERENCIA N SUBGERENCIA N
GERENCIA N DIRECCIÓN N GERENCIA N
DIRECCIÓN N DIRECCIÓN N
我很欣赏有关如何实现这一目标的任何线索。提前谢谢!
答案 0 :(得分:1)
查看分层查询(例如here或here)。 假设您按如下方式创建表:
create table dgsj -- dgsj: DIRECCION, GERENCIA, SUBGERENCIA, JEFATURA
as
select 1 cddepartment, 'DIRECCION_1' nmdepartment, NULL cddeptowner from dual union all
select 2, 'GERENCIA_1', 1 from dual union all
select 3, 'SUBGERENCIA_1', 2 from dual union all
select 4, 'JEFATURA_1', 3 from dual union all
select 5, 'DIRECCION_2', NULL from dual union all
select 6, 'GERENCIA_2', 5 from dual union all
select 7, 'SUBGERENCIA_2', 6 from dual union all
select 8, 'JEFATURA_2', 7 from dual union all
select 9, 'GERENCIA_3', NULL from dual union all
select 10, 'SUBGERENCIA_3', 9 from dual union all
select 11, 'JEFATURA_3', 10 from dual union all
select 12, 'GERENCIA_4', NULL from dual union all
select 13, 'SUBGERENCIA_4', 12 from dual union all
select 14, 'DIRECCION_5', NULL from dual union all
select 15, 'SUBGERENCIA_5', 14 from dual union all
select 16, 'JEFATURA_5', 15 from dual ;
易于阅读:
select * from dgsj;
CDDEPARTMENT NMDEPARTMENT CDDEPTOWNER
1 DIRECCION_1 NULL
2 GERENCIA_1 1
3 SUBGERENCIA_1 2
4 JEFATURA_1 3
5 DIRECCION_2 NULL
6 GERENCIA_2 5
7 SUBGERENCIA_2 6
8 JEFATURA_2 7
9 GERENCIA_3 NULL
10 SUBGERENCIA_3 9
11 JEFATURA_3 10
12 GERENCIA_4 NULL
13 SUBGERENCIA_4 12
14 DIRECCION_5 NULL
15 SUBGERENCIA_5 14
16 JEFATURA_5 15
查询
以下查询返回所有部门名称和"路径"表示层次结构,以及ID,级别和父ID。
select
cddepartment as id
, nmdepartment
, sys_connect_by_path( nmdepartment, '/' ) full_path
, level as lvl
, case
when cddeptowner is null then '-'
else to_char( cddeptowner )
end parent
from dgsj
start with cddeptowner is null
connect by cddeptowner = prior cddepartment
order by level, cddeptowner, cddepartment ;
-- result
ID NMDEPARTMENT FULL_PATH LVL PARENT
1 DIRECCION_1 /DIRECCION_1 1 -
5 DIRECCION_2 /DIRECCION_2 1 -
9 GERENCIA_3 /GERENCIA_3 1 -
12 GERENCIA_4 /GERENCIA_4 1 -
14 DIRECCION_5 /DIRECCION_5 1 -
2 GERENCIA_1 /DIRECCION_1/GERENCIA_1 2 1
6 GERENCIA_2 /DIRECCION_2/GERENCIA_2 2 5
10 SUBGERENCIA_3 /GERENCIA_3/SUBGERENCIA_3 2 9
13 SUBGERENCIA_4 /GERENCIA_4/SUBGERENCIA_4 2 12
15 SUBGERENCIA_5 /DIRECCION_5/SUBGERENCIA_5 2 14
3 SUBGERENCIA_1 /DIRECCION_1/GERENCIA_1/SUBGERENCIA_1 3 2
7 SUBGERENCIA_2 /DIRECCION_2/GERENCIA_2/SUBGERENCIA_2 3 6
11 JEFATURA_3 /GERENCIA_3/SUBGERENCIA_3/JEFATURA_3 3 10
16 JEFATURA_5 /DIRECCION_5/SUBGERENCIA_5/JEFATURA_5 3 15
4 JEFATURA_1 /DIRECCION_1/GERENCIA_1/SUBGERENCIA_1/JEFATURA_1 4 3
8 JEFATURA_2 /DIRECCION_2/GERENCIA_2/SUBGERENCIA_2/JEFATURA_2 4 7
根据您的要求,这可能需要一些调整。 使用Oracle 12c和Oracle 11g(dbfiddle)进行测试。
UPDATE(使用@David Faber的方法将full_path分成4列)
select
nmdepartment
, nvl( TRIM('/' FROM REGEXP_SUBSTR(full_path, '/DIRECCION_\d+')), '-' ) AS direccion
, nvl( TRIM('/' FROM REGEXP_SUBSTR(full_path, '/GERENCIA_\d+')), '-' ) AS gerencia
, nvl( TRIM('/' FROM REGEXP_SUBSTR(full_path, '/SUBGERENCIA_\d+')), '-' ) AS subgerencia
, nvl( TRIM('/' FROM REGEXP_SUBSTR(full_path, '/JEFATURA_\d+')), '-' ) AS jefatura
from (
select
cddepartment as id
, nmdepartment
, sys_connect_by_path( nmdepartment, '/' ) full_path
, level as lvl
, case
when cddeptowner is null then '-'
else to_char( cddeptowner )
end parent
from dgsj
start with cddeptowner is null
connect by cddeptowner = prior cddepartment
order by level, cddeptowner, cddepartment
) ;
结果
NMDEPARTMENT DIRECCION GERENCIA SUBGERENCIA JEFATURA
DIRECCION_1 DIRECCION_1 - - -
DIRECCION_2 DIRECCION_2 - - -
GERENCIA_3 - GERENCIA_3 - -
GERENCIA_4 - GERENCIA_4 - -
DIRECCION_5 DIRECCION_5 - - -
GERENCIA_1 DIRECCION_1 GERENCIA_1 - -
GERENCIA_2 DIRECCION_2 GERENCIA_2 - -
SUBGERENCIA_3 - GERENCIA_3 SUBGERENCIA_3 -
SUBGERENCIA_4 - GERENCIA_4 SUBGERENCIA_4 -
SUBGERENCIA_5 DIRECCION_5 - SUBGERENCIA_5 -
SUBGERENCIA_1 DIRECCION_1 GERENCIA_1 SUBGERENCIA_1 -
SUBGERENCIA_2 DIRECCION_2 GERENCIA_2 SUBGERENCIA_2 -
JEFATURA_3 - GERENCIA_3 SUBGERENCIA_3 JEFATURA_3
JEFATURA_5 DIRECCION_5 - SUBGERENCIA_5 JEFATURA_5
JEFATURA_1 DIRECCION_1 GERENCIA_1 SUBGERENCIA_1 JEFATURA_1
JEFATURA_2 DIRECCION_2 GERENCIA_2 SUBGERENCIA_2 JEFATURA_2
Dbfiddle here。