2013-06-28 2 views
11

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

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

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. Любые предложения, идеи и т. Д. Получили бы большую оценку. Это кажется близким, но я не уверен, что это то, что я ищу: Retrieve all Children and their Children, recursive SQL

На основании (Retrieve all Children and their Children, recursive SQL) Я также пробовал следующее, но получаю «незаконную ссылку на имя запроса в WITH clause» error :

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

Я не понимаю, как кол-во должно быть вычислено. Пожалуйста, объясни. –

+1

Привет, Олаф. Эта конкретная структура моделирует спецификацию (BOM). Это способ описания компонентов, составляющих другие компоненты. Короче говоря, компоненты qtys мультипликативны. Например, если в 25 есть 2 27, тогда в 25 будет 4 31. Оглядываясь назад, я сделал опечатку в своем оригинальном посте. Там должно быть только 1 30 в 25. –

ответ

6

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

+0

ThinkJet, это отлично работает! После того, как я угнал с 10 до 11 г R2, все, что мне нужно было сделать, это скопировать и вставить, и это сработало как шарм. Единственное, что я изменил, - это умножить вместо добавления, что дало мне правильные значения. Я был полностью удивлен как вы, так и ответы Алекса. Это очень помогло мне! –

+0

На вопрос, можете ли вы ...Когда я пытаюсь превратить ваш запрос в представление, я получаю SQL Parse Exception: Error (s) разбор SQL: синтаксическая ошибка рядом с *! * В следующем: с *! * Recursion_view (base, parent_id, child_id, qty) as ( Ошибка синтаксиса около *! * в следующем: с recursion_view *! * (base, parent_id, child_id, qty) as ( –

+0

В зависимости от того, как я пытаюсь создать представление, получаю 28 июня 2013 г. 12: 42:41 oracle.dbtools.db.DBUtil handleException SEVERE: предупреждение, необработанное исключение: закрытое соединение и еще один SEVERE: предупреждение, необработанное исключение: ORA-00600: внутренний код ошибки, аргументы: [qkebCreateColInFro: 1], [], [], [], [], [], [], [], [], [], [], [] –

10

Вы близки:

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 дает основание parent_id.

SQL Fiddle.

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

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

Алекс, спасибо! В то время как я пошел с ответом ThinkJet, это все, что я искал. Если бы я мог вас поддержать, я бы это сделал. –

+0

Согласен с @WillLovett :-) – ThinkJet