earachefl
earachefl

Reputation: 1890

Oracle - get both children and grandparents

I need to get the children of a given node, along with a field that belongs to their highest ancestor. I know how to get both, individually, and I could probably figure out how to programatically combine the two later; but I'd prefer to do it all in one query.

Assuming my table includes the fields id, item_id, code, and name, and that an item_id of 0 is a root node, and that my tree looks like:

id   item_id  code      name    level
------------------------------------
1    0                  Root    1
2    1        my_value  Child1  2
3    2                  Child2  3

I can get the nodes I need using:

select id, item_id, code, name, level from my_table
start with code like '%my_value%'
connect by prior id = item_id

which returns:

id   item_id  code      name    level
-------------------------------------
2    1        my_value  Child1  2
3    2                  Child2  3

I'd like to also get the name field from the highest ancestor(s) of these nodes. I can get those nodes using:

select id, item_id, code, name, level from my_table
where level = (
    select max(level) as max_level from my_table
    start with code like '%my_value%'
    connect by prior item_id = id
)
start with code like '%my_value%'
connect by prior item_id = id

which returns:

id   item_id  code      name    level
-------------------------------------
1    0                  Root    1

I'd like to add the name field returned from the above query as an additional field added to the two nodes returned from the first query, i.e.

id   item_id  code      name    root_name   level
------------------------------------------------
2    1        my_value  Child1  Root        2
3    2                  Child2  Root        3

I hope that's clear. Any suggestions?

Upvotes: 1

Views: 1551

Answers (1)

DazzaL
DazzaL

Reputation: 21973

perhaps start from the root, and then filter afterwards to limit to starting with codes like my_value?

SQL> select id, item_id, code, name, lvl, root_name
  2    from (select id, item_id, code, name, level lvl, sys_connect_by_path(code, '|') c,
  3                connect_by_root name as root_name
  4             from my_table
  5            start with item_id = 0
  6           connect by prior id = item_id)
  7   where c like '%my_value%';

        ID    ITEM_ID CODE                 NAME              LVL ROOT_NAME
---------- ---------- -------------------- ---------- ---------- ----------
         2          1 my_value             Child1              2 Root
         3          2                      Child2              3 Root

Upvotes: 2

Related Questions