Obtener todos los subtrazados en una consulta jerárquica en Oracle

votos
0

Tengo una tabla que contiene una lista de los departamentos de ventas de la siguiente manera:

+-------+---------------+-----------+
|DEPT_ID|DEPT_NAME      |DEPT_PARENT|
+-------+---------------+-----------+
|5500   |World          |           |
|5510   |Region 1       |5500       |
|5511   |Cell 1 Region 1|5510       |
|5512   |Cell 2 Region 1|5510       |
|5513   |Cell 3 Region 1|5510       |
|5514   |Cell 4 Region 1|5510       |
|5515   |Cell 5 Region 1|5510       |
|5520   |Region 2       |5500       |
|5521   |Cell 1 Region 2|5520       |
|5522   |Cell 2 Region 2|5520       |
|5530   |Region 3       |5500       |
|5531   |Cell 1 Region 3|5530       |
|5532   |Cell 2 Region 3|5530       |
|5540   |Region 4       |5500       |
|5533   |Cell 1 Region 4|5540       |
|5534   |Cell 2 Region 4|5533       |
|5590   |Region 5       |5500       |
|5591   |Cell 1 Region 5|5590       |
+-------+---------------+-----------+

Necesito una consulta que devuelve todos los posibles subtrazados. Así que para las tres primeras filas que debe ser el siguiente:

5500 5510
5500 5511
5510 5511

por lo que para cada posible subtrazado volvería el primer y último departamento del camino. Es bastante fácil de obtener la ruta al hacer esto:

    SELECT d.*, LTRIM (SYS_CONNECT_BY_PATH (dept_id, '-'), '-') AS PATH
      FROM depts d
START WITH dept_parent IS NULL
CONNECT BY PRIOR dept_id = dept_parent

pero ¿cómo puedo conseguir todas las posibles subtrazados?

Publicado el 13/01/2020 a las 23:56
fuente por usuario
En otros idiomas...                            


2 respuestas

votos
0

Entiendo que desea generar una tabla de cierre, que contiene todos los caminos posibles en la jerarquía.

Aquí es una solución que utiliza una consulta recursiva estándar para lograrlo. También he añadido una columna que almacena la profundidad de la relación, ya que esta información es a menudo útil en tablas de cierre.

with cte(node_id, dept_id, dept_parent, lvl) as (
    select dept_id node_id, dept_id, dept_parent, 0 lvl from dept
    union all 
    select c.node_id, d.dept_id, d.dept_parent, c.lvl + 1
    from cte c
    inner join dept d on d.dept_id = c.dept_parent
)
select dept_id ancestor, node_id node, lvl 
from cte 
where lvl > 0
order by node, ancestor

Esta demostración de DB violín con los datos de la muestra produce 30 filas, cuyos primeros 10 son:

ANTEPASADO | NODO | LVL
-------: | ---: | -:
    5500 | 5510 | 1
    5500 | 5511 | 2
    5510 | 5511 | 1
    5500 | 5512 | 2
    5510 | 5512 | 1
    5500 | 5513 | 2
    5510 | 5513 | 1
    5500 | 5514 | 2
    5510 | 5514 | 1
    5500 | 5515 | 2
Respondida el 14/01/2020 a las 00:39
fuente por usuario

votos
1

Utilizar CONNECT_BY_ROOTpara encontrar el inicio de la ruta.

Configuración de Oracle :

CREATE TABLE depts ( DEPT_ID, DEPT_NAME, DEPT_PARENT ) AS
SELECT 5500, 'World',           NULL FROM DUAL UNION ALL
SELECT 5510, 'Region 1',        5500 FROM DUAL UNION ALL
SELECT 5511, 'Cell 1 Region 1', 5510 FROM DUAL UNION ALL
SELECT 5512, 'Cell 2 Region 1', 5510 FROM DUAL UNION ALL
SELECT 5513, 'Cell 3 Region 1', 5510 FROM DUAL UNION ALL
SELECT 5514, 'Cell 4 Region 1', 5510 FROM DUAL UNION ALL
SELECT 5515, 'Cell 5 Region 1', 5510 FROM DUAL UNION ALL
SELECT 5520, 'Region 2',        5500 FROM DUAL UNION ALL
SELECT 5521, 'Cell 1 Region 2', 5520 FROM DUAL UNION ALL
SELECT 5522, 'Cell 2 Region 2', 5520 FROM DUAL UNION ALL
SELECT 5530, 'Region 3',        5500 FROM DUAL UNION ALL
SELECT 5531, 'Cell 1 Region 3', 5530 FROM DUAL UNION ALL
SELECT 5532, 'Cell 2 Region 3', 5530 FROM DUAL UNION ALL
SELECT 5540, 'Region 4',        5500 FROM DUAL UNION ALL
SELECT 5533, 'Cell 1 Region 4', 5540 FROM DUAL UNION ALL
SELECT 5534, 'Cell 2 Region 4', 5533 FROM DUAL UNION ALL
SELECT 5590, 'Region 5',        5500 FROM DUAL UNION ALL
SELECT 5591, 'Cell 1 Region 5', 5590 FROM DUAL;

consulta :

SELECT CONNECT_BY_ROOT( dept_parent ) AS ancestor,
       dept_id,
       SYS_CONNECT_BY_PATH( dept_parent, '>' ) || '>' || dept_id AS path
FROM   depts
START WITH dept_parent IS NOT NULL
CONNECT BY PRIOR dept_id = dept_parent;

salida :

ANTEPASADO | DEPT_ID | CAMINO                
-------: | ------: | : -------------------
    5500 | 5510 | > 5500> 5510          
    5500 | 5511 | > 5500> 5510> 5511     
    5500 | 5512 | > 5500> 5510> 5512     
    5500 | 5513 | > 5500> 5510> 5513     
    5500 | 5514 | > 5500> 5510> 5514     
    5500 | 5515 | > 5500> 5510> 5515     
    5500 | 5520 | > 5500> 5520          
    5500 | 5521 | > 5500> 5520> 5521     
    5500 | 5522 | > 5500> 5520> 5522     
    5500 | 5530 | > 5500> 5530          
    5500 | 5531 | > 5500> 5530> 5531     
    5500 | 5532 | > 5500> 5530> 5532     
    5500 | 5540 | > 5500> 5540          
    5500 | 5533 | > 5500> 5540> 5533     
    5500 | 5534 | > 5500> 5540> 5533> 5534
    5500 | 5590 | > 5500> 5590          
    5500 | 5591 | > 5500> 5590> 5591     
    5510 | 5511 | > 5510> 5511          
    5510 | 5512 | > 5510> 5512          
    5510 | 5513 | > 5510> 5513          
    5510 | 5514 | > 5510> 5514          
    5510 | 5515 | > 5510> 5515          
    5520 | 5521 | > 5520> 5521          
    5520 | 5522 | > 5520> 5522          
    5530 | 5531 | > 5530> 5531          
    5530 | 5532 | > 5530> 5532          
    5533 | 5534 | > 5533> 5534          
    5540 | 5533 | > 5540> 5533          
    5540 | 5534 | > 5540> 5533> 5534     
    5590 | 5591 | > 5590> 5591          

db <> violín aquí

Respondida el 14/01/2020 a las 00:50
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more