2

I have a table with a structure like (id, parent_id) in Oracle11g.

id    parent_id
---------------
1     (null)
2     (null)
3     1
4     3
5     3
6     2
7     2

I'd like to query it to get all the lines that are hierarchically linked to each of these id, so the results should be :

root_id  id    parent_id
------------------------
1        3     1
1        4     3
1        5     3
2        6     2
2        7     2
3        4     3
3        5     3

I've been struggling with the connect by and start with for quite some time now, and all i can get is a fraction of the results i want with queries like :

select connect_by_root(id) root_id, id, parent_id from my-table
start with id=1
connect by prior id = parent_id

I'd like to not use any for loop to get my complete results.

Any Idea ?

Best regards, Jérôme Lefrère

PS : edited after first answer, noticing me i had forgotten some of the results i want...

3 Answers 3

3

The query you posted is missing the from clause and left an underscore out of connect_by_root, but I'll assume those aren't actually the source of your problem.

The following query gives you the result you're looking for:

select * from (
   select connect_by_root(id) root_id, id, parent_id
   from test1
   start with parent_id is null
   connect by prior id = parent_id)
where root_id <> id

The central problem is that you were specifying a specific value to start from, rather that specifying a way to identify the root rows. Changing id = 1 to parent_id is null allows the entire contents of the table to be returned.

I also added the outer query to filter the root rows out of the result set, which wasn't mentioned in your question, but was shown in your desired result.

SQL Fiddle Example


Comment Response:

In the version provided, you do get descendants of id = 3, but not in such a way that 3 is the root. This is because we're starting at the absolute root. Resolving this is easy, just omit the start with clause:

SELECT *
FROM
  (SELECT connect_by_root(id) root_id,
          id,
          parent_id
   FROM test1
CONNECT BY
   PRIOR id = parent_id)
WHERE root_id <> id

SQL Fiddle Example

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your answer. I edited my post so the from and missing underscore are not a problem anymore. Your query gets me the absolute roots. I'd like to get also the descendants of the id=3 line
2

try this:

select connect_by_root(id) root_id, id, parent_id
from your_table
start with parent_id is null
connect by prior id = parent_id

3 Comments

Thanks for your answer which was perfect until I noticed that I forgot some of the results i want : i want also the lines that are not absolute roots (see the last 2 results of my original post)
then just remove the start with parent_id is null part
It seems to work. Just need to check this on my more complex table to be sure
0

It will give you the exact result you want:

select connect_by_root(id) as root, id, parent_id
from test1
connect by prior id=parent_id
start with parent_id is not null;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.