创建具有特定结构的部门的视图

时间:2018-03-19 22:12:51

标签: sql oracle

我有一个具有以下部门结构的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

我很欣赏有关如何实现这一目标的任何线索。提前谢谢!

1 个答案:

答案 0 :(得分:1)

查看分层查询(例如herehere)。 假设您按如下方式创建表:

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