hierarchical queries

dwarak.k's picture

A relational database does not store data in a hierarchical way. Then how do I get the data in a hierarchical manner? Here we get to know about how to use the hierarchical querying feature which Oracle has given. This article talks about how you can interpret the hierarchical query conceptually and build hierarchical queries catering your needs.

Using hierarchical queries, you can retrieve records from a table by their natural relationship. Be it a family tree or a employee/manager tree or what ever.

Tree walking enables you to construct a hierarchical tree if the relationship lie in the same table. For instance, a manager column which exists in the emp table which defines the managerial hierarchy.

We shall take up an example of the emp table in Scott schema. Here King is top most in the hierarchy

empno	ename	job	mgr	hiredate
7369	SMITH	CLERK	7902	17-Dec-80
7499	ALLEN	SALESMAN  7698	20-Feb-81
7521	WARD	SALESMAN  7698	22-Feb-81
7566	JONES	MANAGER	7839	2-Apr-81
7654	MARTIN	SALESMAN  7698	28-Sep-81
7698	BLAKE	MANAGER	7839	1-May-81
7782	CLARK	MANAGER	7839	9-Jun-81
7788	SCOTT	ANALYST	7566	19-Apr-87
7839	KING	PRESIDENT	17-Nov-81
7844	TURNER	SALESMAN  7698	8-Sep-81
7876	ADAMS	CLERK	7788	23-May-87
7900	JAMES	CLERK	7698	3-Dec-81
7902	FORD	ANALYST	7566	3-Dec-81
7934	MILLER	CLERK	7782	23-Jan-82

If we have to query the employees reporting to King directly,

SELECT empno, 
       ename, 
       job, 
       mgr, 
       hiredate 
FROM   emp 
WHERE  mgr = 7839

7566	JONES	MANAGER	7839	2-Apr-81
7698	BLAKE	MANAGER	7839	1-May-81
7782	CLARK	MANAGER	7839	9-Jun-81

But if we have to walk down the tree and check who all are reporting to Jones, Blake and Clark (recursively)

SELECT empno, 
       ename, 
       job, 
       mgr, 
       hiredate 
FROM   emp 
START WITH mgr IS NULL 
CONNECT BY PRIOR empno = mgr

We will quickly see what are all the key words used in this query.

START WITH – Specifies the root rows of the hierarchy or in other words, where to start parsing from. This clause is necessary for true hierarchical queries

CONNECT BY PRIOR – This explains the relationship between the parent and the child.

PRIOR – This is used to achieve the recursive condition (The actual walking)

Direction of walking the tree

To explain more on the CONNECT BY clause, this is used to determine if you are walking from top to bottom or bottom to top.

CONNECT BY PRIOR col_1 = col_2


If walking from top to bottom

col_1 is the parent Key(One which identifies the parent) and col_2 is the child key (this identifies the child)
And here it is

CONNECT BY PRIOR empno = mgr

SELECT empno, 
       ename, 
       job, 
       mgr, 
       hiredate,
 level 
FROM   emp 
START WITH mgr IS NULL 
CONNECT BY PRIOR empno = mgr

Gets me this result

7839	KING      PRESIDENT 	           17-Nov-81	1
7566	JONES     MANAGER   7839	2-Apr-81	2
7788	SCOTT     ANALYST   7566	19-Apr-87	3
7876	ADAMS     CLERK     7788	23-May-87	4
7902	FORD      ANALYST   7566	3-Dec-81	3
7369	SMITH     CLERK     7902	17-Dec-80	4
7698	BLAKE     MANAGER   7839	1-May-81	2
7499	ALLEN     SALESMAN  7698	20-Feb-81	3
7521	WARD      SALESMAN  7698	22-Feb-81	3
7654	MARTIN    SALESMAN  7698	28-Sep-81	3
7844	TURNER    SALESMAN  7698	8-Sep-81	3
7900	JAMES     CLERK     7698	3-Dec-81	3
7782	CLARK     MANAGER   7839	9-Jun-81	2
7934	MILLER    CLERK     7782	23-Jan-82	3

If walking from bottom to top
Col_1 should be the child key and col_2 should be the parent key

CONNECT BY PRIOR mgr = empno

Using Level

LEVEL psedo column shows the level or rank of the particular row in the hierarchical tree. If you see the below query, It shows the level of KING and the level of the guys reporting directly to him

SELECT empno, 
       ename, 
       job, 
       mgr, 
       hiredate, 
       LEVEL 
FROM   emp 
WHERE  LEVEL <= 2 
START WITH mgr IS NULL 
CONNECT BY PRIOR empno = mgr

empno	ename	job	mgr	hiredate	level
7839	KING	PRESIDENT		17-Nov-81	1
7566	JONES	MANAGER	7839	2-Apr-81	2
7698	BLAKE	MANAGER	7839	1-May-81	2
7782	CLARK	MANAGER	7839	9-Jun-81	2

Here The level is used in the where clause to restrict the records till the second level.

Level also can be used to format the Output to form a graph structure

SELECT Lpad(ename,Length(ename) + LEVEL * 10 - 10,'-') 
FROM   emp 
START WITH mgr IS NULL 
CONNECT BY PRIOR empno = mgr

KING
----------JONES
--------------------SCOTT
------------------------------ADAMS
--------------------FORD
------------------------------SMITH
----------BLAKE
--------------------ALLEN
--------------------WARD
--------------------MARTIN
--------------------TURNER
--------------------JAMES
----------CLARK
--------------------MILLER

[h2]Pruning branches/children[h2]

There might be business requirements to partially retrieve a hierarchical tree and to prune branches.
If you do not want to do so, use the where condition to restrict the branch but process the child row

SELECT empno, 
       ename, 
       job, 
       mgr, 
       hiredate 
FROM   emp 
WHERE  ename <> 'JONES' 
START WITH mgr IS NULL 
CONNECT BY PRIOR empno = mgr

This will restrict the value Jones in the result set but will still will retrieve Scott and Ford.

Please refer to the attached Picture to get a complete understanding.

To Restrict the value clark and its children, you should be adding the condition after the CONNECT BY

SELECT empno, 
       ename, 
       job, 
       mgr, 
       hiredate 
FROM   emp 
START WITH mgr IS NULL 
CONNECT BY PRIOR empno = mgr 
                 AND ename <> 'CLARK'

Good

It was clear flow of information.Simple example superb explanation.
Thanks a lot

hierarchical queries

Very informative article. It helps to see data in a structured way.
I frequently use this to view Oracle explain plans. The SQL below (from Oracle documentation) shows how to read explain plans.

SELECT lpad(' ',level-1)||operation||' '||options||' '||
object_name "Plan"
FROM plan_table
CONNECT BY prior id = parent_id
AND prior statement_id = statement_id
START WITH id = 0 AND statement_id = '&1'
ORDER BY id;

&1 is where you put your statement_id.

Level

hi all, can anyone tell me how oracle find this level automatically.

Bye

level is a part of the start

level is a part of the start with/connect by syntax.
Here is how Oracle comes up with the levels:

The START WITH condition tells Oracle from where to start assigning the level. In this particular example there is only one row that matches the condition where "mgr is NULL" so there is only one row with level 1.
The CONNECT BY PRIOR clause tells Oracle how to build the hierarchy of levels.

Create a table with the above example and play with it.

Hope this helps
Sumit

Hi sumit

Hi sumit ,
Can u solve one of my problem
I m getting
http://127.0.0.1:2311/l26K6yZtIrDMBfbSeg7Mryj0NWyk3eDHcsH1frlfHxtTVR39
in my address bar while running my forms through form10g.

Can u please help me.

manudu20

Hi

I am not able to open the link u sent.

Sumit

viewing explain plan information

The new way to view explain plan information is as follows :

explain plan set statement_id='blahblah' for .....

followed by :

select * from table(dbms_xplan.display);

Hans

manudu20

Hi manudu20

I am not able to open the link u sent.

Sumit