web-dev-qa-db-fra.com

Comment récupérer tous les enfants récursifs de la ligne parent dans Oracle SQL?

J'ai une requête récursive qui repousse vraiment les limites de ce Java connaissances SQL du singe. Maintenant qu'il est enfin 1h30 du matin, il est probablement temps de commencer à chercher de l'aide. est l'une des rares fois où Google m'a échoué.

Le tableau est le suivant:

Parent_ID CHILD_ID QTY
25        26        1
25        27        2
26        28        1
26        29        1
26        30        2
27        31        1
27        32        1
27        33        2

J'essaie d'obtenir le résultat suivant, où le parent a chaque enfant répertorié en dessous d'eux. Notez que la cascade de quantité aussi.

BASE    PARENT_ID  CHILD_ID   QTY
25         25        26        1
25         25        27        2
25         26        28        1
25         26        29        1
25         26        30        1
25         27        31        2
25         27        32        2
25         27        33        4
26         26        28        1
26         26        29        1
26         26        30        2
27         27        31        1
27         27        32        1
27         27        33        2

J'ai essayé plusieurs dérogations de ce qui suit en vain.

SELECT *
FROM MD_BOMS
START WITH PARENT_ID is not null
CONNECT BY PRIOR CHILD_ID = PARENT_ID
ORDER BY PARENT_ID, CHILD_ID

J'utilise la base de données Oracle. Toutes suggestions, idées, etc. seraient grandement appréciées. Cela semble proche, mais je ne sais pas si c'est ce que je recherche: Récupérer tous les enfants et leurs enfants, SQL récursif

Basé sur ( Récupérer tous les enfants et leurs enfants, SQL récursif ) J'ai également essayé ce qui suit mais je reçois une erreur "référence illégale d'un nom de requête dans la clause WITH":

with cte as (
    select  CHILD_ID, PARENT_ID, CHILD_ID as head
    from    MD_BOMS
    where   PARENT_ID is not null
    union all
    select  ch.CHILD_ID, ch.PARENT_ID, p.head
    from    MD_BOMS ch
    join    cte pa
    on      pa.CHILD_ID = ch.PARENT_ID
)
select  *
from    cte
14
Will Lovett

La réponse @AlexPoole est excellente, je veux juste étendre sa réponse avec une variante de requête plus intuitive pour additionner des valeurs le long d'un chemin.
Cette variante basée sur factorisation de sous-requête récursive , introduite dans Oracle 11g R2.

with recursion_view(base, parent_id, child_id, qty) as (
   -- first step, get rows to start with
   select 
     parent_id base, 
     parent_id, 
     child_id, 
     qty
  from 
    md_boms

  union all

  -- subsequent steps
  select
    -- retain base value from previous level
    previous_level.base,
    -- get information from current level
    current_level.parent_id,
    current_level.child_id,
    -- accumulate sum 
    (previous_level.qty + current_level.qty) as qty 
  from
    recursion_view previous_level,
    md_boms        current_level
  where
    current_level.parent_id = previous_level.child_id

)
select 
  base, parent_id, child_id, qty
from 
  recursion_view
order by 
  base, parent_id, child_id

exemple SQLFiddle (étendu avec une ligne de données pour démontrer le travail avec plus de 2 niveaux)

8
ThinkJet

Tu es proche:

select connect_by_root parent_id base, parent_id, child_id, qty
from md_boms
connect by prior child_id = parent_id
order by base, parent_id, child_id;

          BASE  PARENT_ID   CHILD_ID        QTY
    ---------- ---------- ---------- ----------
            25         25         26          1 
            25         25         27          2 
            25         26         28          1 
            25         26         29          1 
            25         26         30          2 
            25         27         31          1 
            25         27         32          1 
            25         27         33          2 
            26         26         28          1 
            26         26         29          1 
            26         26         30          2 
            27         27         31          1 
            27         27         32          1 
            27         27         33          2 

     14 rows selected 

Le connect_by_root opérateur vous donne la base parent_id.

SQL Fiddle .

Je ne sais pas comment vous calculez votre qty. Je suppose que vous voulez le total du chemin vers l'enfant, mais cela ne correspond pas à ce que vous avez montré. Comme point de départ, alors, en empruntant très fortement à cette réponse , vous pouvez essayer quelque chose comme:

with hierarchy as (
  select connect_by_root parent_id base, parent_id, child_id, qty,
    sys_connect_by_path(child_id, '/') as path
  from md_boms
  connect by prior child_id = parent_id
)
select h.base, h.parent_id, h.child_id, sum(e.qty)
from hierarchy h
join hierarchy e on h.path like e.path ||'%'
group by h.base, h.parent_id, h.child_id
order by h.base, h.parent_id, h.child_id;

     BASE  PARENT_ID   CHILD_ID SUM(E.QTY)
---------- ---------- ---------- ----------
        25         25         26          1 
        25         25         27          2 
        25         26         28          2 
        25         26         29          2 
        25         26         30          3 
        25         27         31          3 
        25         27         32          3 
        25         27         33          4 
        26         26         28          1 
        26         26         29          1 
        26         26         30          2 
        27         27         31          1 
        27         27         32          1 
        27         27         33          2 

 14 rows selected 
14
Alex Poole