Hierarchical Queries; If a table contains hierarchical data, then you can select rows in a hierarchical order using the hierarchical query clause:
START WITH specifies the root row(s) of the hierarchy.
CONNECT BY specifies the relationship between parent rows and child rows of the hierarchy.
create table corporate_slaves (
slave_id integer primary key,
supervisor_id references corporate_slaves,
name varchar(100)
);
insert into corporate_slaves values (1, NULL, ‘Big Boss Man’);
insert into corporate_slaves values (2, 1, ‘VP Marketing’);
insert into corporate_slaves values (3, 1, ‘VP Sales’);
insert into corporate_slaves values (4, 3, ‘Joe Sales Guy’);
insert into corporate_slaves values (5, 4, ‘Bill Sales Assistant’);
insert into corporate_slaves values (6, 1, ‘VP Engineering’);
insert into corporate_slaves values (7, 6, ‘Jane Nerd’);
insert into corporate_slaves values (8, 6, ‘Bob Nerd’);
column name format a20
select * from corporate_slaves;
SLAVE_ID SUPERVISOR_ID NAME
———- ————- ——————–
1 Big Boss Man
2 1 VP Marketing
3 1 VP Sales
4 3 Joe Sales Guy
5 4 Bill Sales Assistant
6 1 VP Engineering
7 6 Jane Nerd
8 6 Bob Nerd
8 rows selected.
– With the Oracle CONNECT BY clause, you can get all the rows out at once:
set pagesize 100
select name, slave_id, supervisor_id
from corporate_slaves
connect by prior slave_id = supervisor_id;
NAME SLAVE_ID SUPERVISOR_ID
——————– ———- ————-
VP Marketing 2 1
VP Sales 3 1
Joe Sales Guy 4 3
Bill Sales Assistant 5 4
VP Engineering 6 1
Jane Nerd 7 6
Bob Nerd 8 6
Joe Sales Guy 4 3
Bill Sales Assistant 5 4
Bill Sales Assistant 5 4
Jane Nerd 7 6
Bob Nerd 8 6
Big Boss Man 1
VP Marketing 2 1
VP Sales 3 1
Joe Sales Guy 4 3
Bill Sales Assistant 5 4
VP Engineering 6 1
Jane Nerd 7 6
Bob Nerd 8 6
20 rows selected.
– This seems a little strange. It looks as though Oracle has produced all possible trees and subtrees. Let’s add a START WITH clause:
select name, slave_id, supervisor_id
from corporate_slaves
connect by prior slave_id = supervisor_id
start with slave_id in (select slave_id
from corporate_slaves
where supervisor_id is null);
NAME SLAVE_ID SUPERVISOR_ID
——————– ———- ————-
Big Boss Man 1
VP Marketing 2 1
VP Sales 3 1
Joe Sales Guy 4 3
Bill Sales Assistant 5 4
VP Engineering 6 1
Jane Nerd 7 6
Bob Nerd 8 6
8 rows selected.
SQL> SELECT sys_connect_by_path(name, ‘/’) Path
2 FROM corporate_slaves
3 CONNECT BY PRiOR slave_id = supervisor_id
4 START WiTH slave_id iN
5 (SELECT slave_id
6 FROM corporate_slaves
7 WHERE supervisor_id iS NULL) ;
PATH
————————————————–
/Big Boss Man
/Big Boss Man/VP Marketing
/Big Boss Man/VP Sales
/Big Boss Man/VP Sales/Joe Sales Guy
/Big Boss Man/VP Sales/Joe Sales Guy/Bill Sales Assistant
/Big Boss Man/VP Engineering
/Big Boss Man/VP Engineering/Jane Nerd
/Big Boss Man/VP Engineering/Bob Nerd
SQL> SELECT sys_connect_by_path(name, ‘/’) Path
2 FROM corporate_slaves
3 CONNECT BY slave_id = PRiOR supervisor_id
4 START WiTH slave_id iN
5 (SELECT slave_id
6 FROM corporate_slaves
7 WHERE supervisor_id iS NULL) ;
PATH
————————————————–
/Big Boss Man
SQL> SELECT sys_connect_by_path(name, ‘/’) Path
2 FROM corporate_slaves
3 CONNECT BY PRiOR slave_id = supervisor_id
4 START WiTH slave_id = 3 ;
PATH
————————————————–
/VP Sales
/VP Sales/Joe Sales Guy
/VP Sales/Joe Sales Guy/Bill Sales Assistant
– some functions cant hurt
SELECT name,
slave_id,
supervisor_id,
LEVEL,
sys_connect_by_path(slave_id, ‘/’) Path,
connect_by_isleaf isLeaf
FROM corporate_slaves
CONNECT BY PRiOR slave_id = supervisor_id
START WiTH slave_id iN
(SELECT slave_id
FROM corporate_slaves
WHERE supervisor_id iS NULL)
ORDER BY LEVEL, NAME;
NAME SLAVE_ID SUPERVISOR_ID LEVEL PATH ISLEAF
——————– ———- ————- ———- ——– ———-
Big Boss Man 1 1 /1 0
VP Engineering 6 1 2 /1/6 0
VP Marketing 2 1 2 /1/2 1
VP Sales 3 1 2 /1/3 0
Bob Nerd 8 6 3 /1/6/8 1
Jane Nerd 7 6 3 /1/6/7 1
Joe Sales Guy 4 3 3 /1/3/4 0
Bill Sales Assistant 5 4 4 /1/3/4/5 1
8 rows selected.
http://download-uk.oracle.com/docs/cd/B19306_01/server.102/b14200/queries003.htm#i2053935
http://philip.greenspun.com/sql/trees
http://www.oracle.com/technology/oramag/webcolumns/2003/techarticles/gennick_connectby_10g.html