2013-06-28 12 views
11

Mam kwerendę rekursywną, która naprawdę rozciąga granice wiedzy SQL małp Java. Teraz, kiedy nadszedł czas ostateczny o 1:30, nadszedł czas, aby zacząć szukać pomocy. To jeden z niewielu przypadków, gdy Google mnie zawiódł.Jak odzyskać wszystkie rekurencyjne dzieci z wiersza nadrzędnego w Oracle SQL?

tabela wygląda następująco:

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 

Próbuję uzyskać następujący wynik, gdzie rodzic ma każde dziecko wymienione poniżej nich. Zauważ, że kaskada qty również.

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 

Próbowałem kilku odchyleń poniższych bezskutecznie.

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

Używam bazy danych Oracle. Wszelkie sugestie, pomysły itp. Byłyby mile widziane. Wydaje się być blisko, ale nie jestem pewien, czy to jest to, czego szukam: Retrieve all Children and their Children, recursive SQL

Na podstawie (Retrieve all Children and their Children, recursive SQL) Próbowałem również następujące, ale otrzymałem "niedozwolone odniesienie nazwy zapytania w klauzula WITH" błąd :

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

Nie rozumiem, jak Ilość musi być obliczona. Proszę wytłumacz. –

+1

Witam Olaf. Ta konkretna struktura modeluje zestawienie materiałowe (BOM). Jest to sposób opisywania, jakie komponenty składają się na inne komponenty. Krótko mówiąc, komponenty qtys są multiplikatywne. Na przykład, jeśli w 25 jest 2 27, to w 25 to 4 31. Patrząc wstecz, zrobiłem literówkę w moim oryginalnym poście. Powinno być tylko 1 30 w 25. –

Odpowiedz

6

@AlexPoole odpowiedź jest super, po prostu chcę, aby rozszerzyć swoją odpowiedź z bardziej intuicyjnego wariantu zapytania o zsumowanie wartości wzdłuż ścieżki.
Ten wariant oparty na funkcji recursive subquery factoring, wprowadzony w 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 (rozszerzony o jeden wiersz danych, aby wykazać pracy z więcej niż 2 poziomy)

+0

ThinkJet, działa to świetnie! Po zryczałtowaniu od 10g do 11g R2, wszystko co musiałem zrobić, to skopiować i wkleić i działało jak czar. Jedyną rzeczą, którą zmieniłem, było wielokrotne wstawianie zamiast dodawania, co dało mi prawidłowe ilości. Byłem całkowicie zaskoczony zarówno przez ciebie, jak i odpowiedzi Alexa. To mi pomogło! –

+0

Więcej pytań, czy możesz ...Kiedy próbuję przekształcić zapytanie w widok, otrzymuję wyjątek SQL Parse: Błąd podczas analizowania SQL: błąd składniowy w pobliżu *! * W następującej postaci: z *! * Recursion_view (podstawa, nadrzędny identyfikator, dziecko_id, qty) jako ( błąd składniowy w pobliżu *! * w następującej lokalizacji: z widokiem rekurencji *! * (podstawa, nadrzędny identyfikator, dziecko_id, qty) jako ( –

+0

W zależności od tego, jak próbuję utworzyć widok, otrzymuję 28 czerwca 2013 12: 42:41 PM oracle.dbtools.db.DBUtil handleException SEVERE: Ostrzeżenie, nieobsługiwany wyjątek: Zamknięte połączenie I jeszcze inny POWAŻNY: Ostrzeżenie, nieobsługiwany wyjątek: ORA-00600: wewnętrzny kod błędu, argumenty: [qkebCreateColInFro: 1], [], [], [], [], [], [], [], [], [], [], [] –

10

Jesteś blisko:

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 

connect_by_root operator daje podstawę parent_id.

SQL Fiddle.

Nie jestem pewien, jak obliczasz swoją qty. Zgaduję, że chcesz, aby suma była ścieżką do dziecka, ale to nie pasuje do tego, co pokazałeś. Jako punkt wyjścia, a następnie, pożyczanie bardzo ciężko od this answer, można spróbować czegoś takiego:

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, dziękuję! Kiedy poszedłem z odpowiedzią ThinkJet, to wszystko, czego szukałem. Gdybym mógł cię upomnieć, zrobiłbym to. –

+0

Zgadzam się z @WillLovett :-) – ThinkJet

Powiązane problemy