Oracle CTE Hierarchy CONNECT BY
▌Problem
Assume that we have a table, EMPLOYEES, which include hierarchy data like
this,
Each employee has a manager, and a
manager also has his/her manager, except JB, who is the boss.
We are going to learn how to use the
following 2 ways to traverse the hierarchy rows.
1. START
WITH...CONNECT BY...
2. Recursive CTE
▌START WITH...CONNECT BY...
We can use Oracle's START WITH... CONNECT BY...
clause to traverse hierarchal rows.
▋Pattern
l
START WITH specifies the root row of
the hierarchy.
l
CONNECT BY specifies the
relationship of parent and child rows.
l
PRIOR indicates the recursive
condition to traverse all the rows.
e.q. PRIOR A = B
means using current row's column A to match next row's column B. And A = PRIOR B means
use current row's column B to match next row's column A.
▋SQL
The following SQL lists the top-down
hierarchy by starting from JB that has no manager and traverse the records that have
manager as JB,
and so on.
Notice that the condition to find
next row is PRIOR
EMP_NO = MANAGER_NO, and that means we use EMP_NO to find(match) the next row by
its MANAGER_NO.
Result:
And the following SQL lists the
bottom-up hierarchy by from James and shows his reporting line.
Notice that the condition to find next row is EMP_NO = PRIOR MANAGER_NO, and that means we use MANAGER_NO to find(match) the next row by its EMP_NO.
Result:
▌CTE Recursive
We can do the same thing by using CTE
recursive.
▋SQL
Result:
▌(Optional) Create a Function
Let's create a Function FindReportLine that returns the report line of an exployee by his/her name.
▋Function by START WITH... CONNECT BY...
▋Function by Recursive CTE
▋Use the Function
Since the function returns the rows as SYS_REFCURSOR, we can parse the result by XML.
XMLTABLE maps the result of an XQuery evaluation into relational rows and columns.
The XMLSEQUENCE could also do the same thing, though it's deprecated.
▌(Optional) Aggregate the Result
We can use LISTAGG function in Oracle to combine multiple rows into a single row with each value separated by a specified character or symbol. For example, the following SQL aggregates and show the names of the report line of James.
The result will be "James / Jack / JB".
▌Reference
▋[Sql
Server] Recursive CTE for hierarchy data
▋[PostgreSQL]
Recursive CTE for hierarchy data