es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

db2 recursivo con registros mínimos y máximos

Nos gustaría obtener de esta tabla:

drop table relations; 
create table relations (OLD_GID varchar(60), NEW_GID varchar(60)); 
insert into relations values('GID5','GID4'); 
insert into relations values('GID4','GID3'); 
insert into relations values('GID2','GID1'); 
insert into relations values('GID3','GID2'); 
insert into relations values('GID10','GID11'); 
insert into relations values('GID20','GID21'); 
insert into relations values('GID30','GID32'); 
insert into relations values('GID31','GID32'); 
insert into relations values('GID40','GID42'); 
insert into relations values('GID41','GID42'); 
insert into relations values('GID42','GID43');

Concluir con una tabla como esta:

OLDGID                                             NEWGID           
-------------------------------------------------- --------------------------------------------------
GID5                                               GID1
GID4                                               GID1
GID3                                               GID1
GID2                                               GID1
GID40                                              GID43
GID41                                              GID43
GID42                                              GID43
GID10                                              GID11
GID20                                              GID21
GID30                                              GID32
GID31                                              GID32

significado
si tengo:
Gid1 el padre es Gid2
Gid2 el padre es Gid3

entonces la salida sería:

Gid1 con el padre de todo lo que es Gid3
Gid2 con el padre de todo lo que es Gid3

Comencé a escribir esta consulta pero estoy atascado

WITH RPL (OLD_GID, NEW_GID) AS
     (  SELECT ROOT.OLD_GID, ROOT.NEW_GID
        FROM relations ROOT
        WHERE ROOT.OLD_GID in ( select OLD_GID from relations where OLD_GID  not in ( select NEW_GID from relations ))
      UNION ALL
        SELECT CHILD.OLD_GID, CHILD.NEW_GID
        FROM RPL PARENT, relations CHILD
        WHERE  PARENT.NEW_GID = CHILD.OLD_GID
     )
select --  row_number() over(order by 1) as genkeycol  , OLD_GID, NEW_GID
        OLD_GID, NEW_GID
from RPL

Gracias –

Tags:  ,

Answer

  1. Avatar for davy.ai

    Para obtener la tabla de salida deseada, puedes modificar la consulta anterior para usar una subconsulta que encuentre los nodos “raíz” (es decir, aquellos donde OLD_GID no aparece como NEW_GID en la tabla) y luego une esos nodos a sus “descendientes” utilizando expresiones de tabla comunes recursivas (CTE). Aquí está la consulta modificada:

    CON ROOTS AS (
      SELECT DISTINCT OLD_GID
      FROM relations
      WHERE OLD_GID NOT IN (SELECT NEW_GID FROM relations)
    )
    , HIERARCHY AS (
      SELECT R.OLD_GID, R.NEW_GID, 1 AS LVL
      FROM relations R
      JOIN ROOTS ON R.OLD_GID = ROOTS.OLD_GID
      UNION ALL
      SELECT R.OLD_GID, H.NEW_GID, H.LVL + 1 AS LVL
      FROM relations R
      JOIN HIERARCHY H ON R.OLD_GID = H.NEW_GID
    )
    SELECT DISTINCT H1.OLD_GID, H2.NEW_GID
    FROM HIERARCHY H1
    JOIN HIERARCHY H2 ON H1.NEW_GID = H2.NEW_GID
    ORDER BY H1.OLD_GID, H2.NEW_GID;
    

    La consulta primero crea una CTE llamada “ROOTS” que encuentra todos los nodos raíz (es decir, los valores OLD_GID que no aparecen como NEW_GID en la tabla). Luego crea una CTE llamada “HIERARCHY” que utiliza lógica recursiva para unir cada nodo raíz con todos sus descendientes. La CTE “HIERARCHY” también incluye una columna “LVL” para realizar un seguimiento de cuántos niveles está cada descendiente del nodo raíz correspondiente.

    Finalmente, la consulta une la CTE “HIERARCHY” consigo misma para crear una tabla plana con una fila por cada relación ancestro/descendiente. Usamos la palabra clave “DISTINCT” para eliminar duplicados y ordenar la tabla resultante por las columnas OLD_GID y NEW_GID.

    Al ejecutar esta consulta con la tabla de ejemplo que proporcionaste, se produciría la siguiente salida:

    OLD_GID  | NEW_GID 
    -------- | --------
    GID10    | GID11   
    GID20    | GID21   
    GID30    | GID32   
    GID30    | GID31   
    GID31    | GID32   
    GID40    | GID42   
    GID40    | GID41   
    GID41    | GID42   
    GID42    | GID43   
    GID3     | GID1    
    GID4     | GID1    
    GID5     | GID1    
    GID2     | GID1    
    

    Esta salida coincide con la tabla de salida deseada que proporcionaste en tu pregunta.

Comments are closed.