Search code examples
sqloracle-databaserecursionrdbms

How to retrieve all recursive children of parent row in Oracle SQL?


I've got a recursive query that's really stretching the limits of this Java monkey's SQL knowledge. Now that it's finally 1:30 in the AM, it's probably time to start looking for some help. This is one of the few times Google has failed me.

The table is as follows:

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

I'm trying to get the following result, where the parent has every child listed below them. Note that the qty's cascade as well.

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

I've tried several deviations of the following to no avail.

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

I'm using the Oracle database. Any suggestions, ideas, etc. would be greatly appreciated. This seems close, but I'm not sure if it's what I'm looking for: Retrieve all Children and their Children, recursive SQL

Based on ( Retrieve all Children and their Children, recursive SQL )I've also tried the following but receive an "illegal reference ofa query name in 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

Solution

  • @AlexPoole answer is great, I just want to extend his answer with more intuitive variant of query for summing values along a path.
    This variant based on recursive subquery factoring feature, introduced 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 (extended with one data row to demonstrate work with more then 2 levels)