2013-06-28 18 views
11

Ho una query ricorsiva che sta veramente estendendo i limiti della conoscenza SQL di questa scimmia Java. Ora che è finalmente l'1:30 nell'AM, è probabilmente tempo di iniziare a cercare aiuto. Questa è una delle poche volte in cui Google mi ha deluso.Come recuperare tutti i figli ricorsivi della riga padre in Oracle SQL?

La tabella è la seguente:

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 

Sto cercando di ottenere il seguente risultato, in cui il genitore ha elencato tutti i bambini sotto di loro. Si noti che anche la cascata del qty.

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 

Ho provato diverse deviazioni di quanto segue senza successo.

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

Sto utilizzando il database Oracle. Qualsiasi suggerimento, idea, ecc. Sarebbe molto apprezzato. Questo sembra vicino, ma non sono sicuro se è quello che sto cercando: Retrieve all Children and their Children, recursive SQL

Basato su (Retrieve all Children and their Children, recursive SQL) Ho anche provato quanto segue, ma ricevo un errore "riferimento di riferimento di query nome in WITH clausola" :

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 
+1

non capisco, come qty deve essere calcolato. Spiega per favore. –

+1

Ciao Olaf. Questa particolare struttura modella una distinta base (BOM). È un modo di descrivere quali componenti compongono altri componenti. In breve, i qty dei componenti sono moltiplicativi. Ad esempio, se ci sono 2 27 in un 25, allora ci sarebbero 4 31 in un 25. Guardando indietro, ho fatto un refuso nel mio post originale. Ci dovrebbe essere solo 1 30 in un 25. –

risposta

6

@AlexPoole risposta è grande, voglio solo di estendere la sua risposta con variante più intuitiva di query per sommare i valori lungo un sentiero.
Questa variante basata sulla funzione recursive subquery factoring, introdotta in 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 

SQLFiddle example (esteso con una riga di dati per dimostrare lavorare con più di 2 livelli)

+0

ThinkJet, funziona alla grande! Dopo che ho passato da 10g a 11g R2, tutto quello che dovevo fare era copiare e incollare e funzionava come un incantesimo. L'unica cosa che ho cambiato è stata la moltiplicazione anziché l'aggiunta, che mi ha dato i qty corretti. Sono rimasto completamente sorpreso dalle risposte sia di te che di Alex. Questo mi ha aiutato un po '! –

+0

Su più domande se puoi ...Quando provo a trasformare la tua query in una vista, ricevo una SQL Parse Exception: Error (s) che analizza SQL: errore di sintassi vicino a *! * Nel seguente: con *! * Recursion_view (base, parent_id, child_id, qty) come ( errore di sintassi vicino *! * nel seguente: con recursion_view *! * (base, parent_id, child_id, qty) come ( –

+0

A seconda di come provo a creare la vista, ricevo il 28 giugno 2013 12: 42:41 PM oracle.dbtools.db.DBUtil handleException SEVERE: Avviso, eccezione non gestita: connessione chiusa e un'altra SEVERE: avviso, eccezione non gestita: ORA-00600: codice errore interno, argomenti: [qkebCreateColInFro: 1], [], [], [], [], [], [], [], [], [], [], [] –

10

vi sono vicino:

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 

il connect_by_root operator ti dà la base parent_id.

SQL Fiddle.

Non sono sicuro di come stai calcolando il tuo qty. Immagino che tu voglia il totale per il percorso verso il bambino, ma questo non corrisponde a quello che hai mostrato. Come punto di partenza, quindi, prendendo in prestito molto pesantemente da this answer, si potrebbe provare qualcosa di simile:

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 
+0

Alex, grazie! Mentre sono andato con la risposta di ThinkJet, questo è tutto ciò che stavo cercando. Se potessi invertire te lo farei. –

+0

D'accordo con @WillLovett :-) – ThinkJet

Problemi correlati