Как получить все рекурсивные дети родительской строки в Oracle SQL?

У меня есть рекурсивный запрос, который действительно расширяет границы знаний Java-обезьяны Java. Теперь, когда он наконец 1:30 в AM, возможно, пора начать искать какую-то помощь. Это один из немногих раз, когда Google меня не подвел.

Таблица выглядит следующим образом:

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

Я пытаюсь получить следующий результат, когда родительский список имеет каждый нижеперечисленный ребенок. Обратите внимание, что каскад 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

Я пробовал несколько отклонений от следующего, но безрезультатно.

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

Я использую базу данных Oracle. Любые предложения, идеи и т.д. Получили бы большую оценку. Это кажется близким, но я не уверен, что это то, что я ищу: Извлеките всех детей и их детей, рекурсивный SQL

Основано на (Получить всех детей и их детей, рекурсивный SQL). Я также пробовал следующее, но получаю "незаконную ссылку на имя запроса в предложении 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

Ответ 1

@AlexPoole ответ велик, я просто хочу расширить его ответ более интуитивным вариантом запроса для суммирования значений по пути.
Этот вариант основан на рекурсивном подзапросе факторинг, представленном в 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 (расширен с одной строкой данных, чтобы продемонстрировать работу с более чем двумя уровнями)

Ответ 2

Вы близко:

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 дает вам базу parent_id.

SQL Fiddle.

Я не уверен, как вы рассчитываете свой qty. Я предполагаю, что вы хотите, чтобы общее число для пути к ребенку, но это не соответствует тому, что вы показали. В качестве отправной точки, затем, очень сильно заимствуя этот ответ, вы можете попробовать что-то вроде:

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