Based on the SQLD exam syllabusReport an error
START WITH sets the starting point (root) rows, and CONNECT BY sets the condition that links parents and children. In EMP, the root is KING, the row with MGR IS NULL.PRIOR is the row already found. PRIOR EMPNO = MGR is parent → child (forward direction, top to bottom), and PRIOR MGR = EMPNO is child → parent (reverse direction, bottom to top).LEVEL is the depth, with the root at 1. If you indent with LPAD(' ', 2 * (LEVEL - 1)), the tree shape becomes visible.ORDER SIBLINGS BY. A regular ORDER BY destroys the tree order.The MGR column of EMP holds the manager's EMPNO. Since rows in the same table point to other rows, following them gives you an org chart.
KING (7839, no MGR)
├─ BLAKE (7698) ── ALLEN · JAMES · MARTIN · TURNER · WARD
├─ CLARK (7782) ── MILLER
└─ JONES (7566) ─┬ FORD (7902) ── SMITH
└ SCOTT (7788) ── ADAMSSELECT LEVEL, columns …
FROM table
[WHERE condition to filter the result]
START WITH root condition
CONNECT BY [NOCYCLE] PRIOR parent-side column = child-side column [AND pruning condition]
[ORDER SIBLINGS BY column];| Element | What it does |
|---|---|
START WITH | The rows that become roots. If several rows match the condition, there are several trees |
CONNECT BY | The condition that links the row already found (PRIOR) to the next row |
PRIOR | An operator meaning "of the row found just before" |
LEVEL | A pseudo column: root 1, child 2, grandchild 3 … |
ORDER SIBLINGS BY | Sorts only the siblings under the same parent |
START WITH, every row becomes its own root. SELECT COUNT(*) FROM EMP CONNECT BY PRIOR EMPNO = MGR returned 39 in the practice container. That is the total of the branches below each of the 14 employees.Start at KING and go down toward the subordinates. PRIOR EMPNO = MGR means "the next rows are those whose MGR equals the EMPNO of the previous row".
SELECT LEVEL, RPAD(LPAD(' ', 2 * (LEVEL - 1)) || ENAME, 16) AS TREE, EMPNO, MGR FROM EMP START WITH MGR IS NULL CONNECT BY PRIOR EMPNO = MGR ORDER SIBLINGS BY ENAME; LEVEL TREE EMPNO MGR
---------- ---------------------------------------------------------------- ---------- ----------
1 KING 7839
2 BLAKE 7698 7839
3 ALLEN 7499 7698
3 JAMES 7900 7698
3 MARTIN 7654 7698
3 TURNER 7844 7698
3 WARD 7521 7698
2 CLARK 7782 7839
3 MILLER 7934 7782
2 JONES 7566 7839
3 FORD 7902 7566
4 SMITH 7369 7902
3 SCOTT 7788 7566
4 ADAMS 7876 7788LPAD(' ', 2 * (LEVEL - 1)) makes 0 spaces at LEVEL 1, 2 spaces at 2, and 4 spaces at 3. Putting it before the name makes the indentation.RPAD(…, 16) was added to shrink the width of the result column. The content is the same without it. The long divider line under the TREE column is drawn by SQL*Plus to the column's maximum byte width.PRIOR EMPNO = MGR.| LEVEL | Number of employees | Employees |
|---|---|---|
| 1 | 1 | KING |
| 2 | 3 | BLAKE, CLARK, JONES |
| 3 | 8 | ALLEN, JAMES, MARTIN, TURNER, WARD, MILLER, FORD, SCOTT |
| 4 | 2 | SMITH, ADAMS |
GROUP BY LEVEL also gives 1, 3, 8, 2. The deepest LEVEL is 4.If you change the root, you see only what's below it. This is JONES's organization.
SELECT LEVEL, RPAD(LPAD(' ', 2 * (LEVEL - 1)) || ENAME, 16) AS TREE FROM EMP START WITH ENAME = 'JONES' CONNECT BY PRIOR EMPNO = MGR ORDER SIBLINGS BY ENAME; LEVEL TREE
---------- ----------------------------------------------------------------
1 JONES
2 FORD
3 SMITH
2 SCOTT
3 ADAMSChanging the position of PRIOR flips the direction. PRIOR MGR = EMPNO means "the row whose EMPNO equals the MGR of the previous row", that is, the manager comes next.
SELECT LEVEL, ENAME, MGR FROM EMP START WITH ENAME = 'SMITH' CONNECT BY PRIOR MGR = EMPNO; LEVEL ENAME MGR
---------- ---------- ----------
1 SMITH 7902
2 FORD 7566
3 JONES 7839
4 KING| How it's written | PRIOR side | Direction | How to read it |
|---|---|---|---|
PRIOR EMPNO = MGR | The parent's EMPNO | Forward (parent → child) | Find the people who have my number as their manager |
MGR = PRIOR EMPNO | Same as above | Forward | Swapping the two sides of the equals sign doesn't change the meaning |
PRIOR MGR = EMPNO | The child's MGR | Reverse (child → parent) | Find my manager |
EMPNO = PRIOR MGR | Same as above | Reverse |
START WITH MGR IS NULL CONNECT BY PRIOR MGR = EMPNO returns only the single row KING, because KING's MGR is NULL.⚠️ Pitfall: In
PRIOR EMPNO = MGRandEMPNO = PRIOR MGR, the left side of the equals sign looks like EMPNO in both, but the directions are opposite. If the column with PRIOR is EMPNO, it is forward; if it is MGR, it is reverse.
If you use a regular ORDER BY in a hierarchical query, it does sort, but the shape where children come under their parent is broken.
SELECT ENAME, LEVEL FROM EMP START WITH MGR IS NULL CONNECT BY PRIOR EMPNO = MGR ORDER BY ENAME FETCH FIRST 3 ROWS ONLY;ENAME LEVEL
---------- ----------
ADAMS 4
ALLEN 3
BLAKE 2ORDER SIBLINGS BY ENAME preserves the tree shape and sorts only siblings that share the same parent. That is why, in the forward example above, BLAKE·CLARK·JONES and ALLEN·JAMES·MARTIN·TURNER·WARD are each in name order.| Name | Value it returns |
|---|---|
SYS_CONNECT_BY_PATH(column, 'separator') | A string joining the values from the root to the current row with the separator |
CONNECT_BY_ROOT column | The value from the root row of the tree the current row belongs to (it is an operator, not a function, so no parentheses are needed) |
CONNECT_BY_ISLEAF | 1 if there are no children, 0 if there are |
SELECT ENAME, CONNECT_BY_ROOT ENAME AS ROOT, CONNECT_BY_ISLEAF AS LEAF, SUBSTR(SYS_CONNECT_BY_PATH(ENAME, '/'), 1, 25) AS PATH FROM EMP START WITH MGR IS NULL CONNECT BY PRIOR EMPNO = MGR ORDER SIBLINGS BY ENAME;ENAME ROOT LEAF PATH
---------- ---------- ---------- ----------------------------------------------------------------------------------------------------
KING KING 0 /KING
BLAKE KING 0 /KING/BLAKE
ALLEN KING 1 /KING/BLAKE/ALLEN
JAMES KING 1 /KING/BLAKE/JAMES
MARTIN KING 1 /KING/BLAKE/MARTIN
TURNER KING 1 /KING/BLAKE/TURNER
WARD KING 1 /KING/BLAKE/WARD
CLARK KING 0 /KING/CLARK
MILLER KING 1 /KING/CLARK/MILLER
JONES KING 0 /KING/JONES
FORD KING 0 /KING/JONES/FORD
SMITH KING 1 /KING/JONES/FORD/SMITH
SCOTT KING 0 /KING/JONES/SCOTT
ADAMS KING 1 /KING/JONES/SCOTT/ADAMS/KING/JONES/SCOTT/ADAMS, not KING/JONES/….When there are several roots, CONNECT_BY_ROOT becomes useful. Take the three managers (MANAGER) as roots and keep only the leaf nodes.
SELECT ENAME, CONNECT_BY_ROOT ENAME AS ROOT FROM EMP WHERE CONNECT_BY_ISLEAF = 1 START WITH JOB = 'MANAGER' CONNECT BY PRIOR EMPNO = MGR ORDER SIBLINGS BY ENAME;ENAME ROOT
---------- ----------
ALLEN BLAKE
JAMES BLAKE
MARTIN BLAKE
TURNER BLAKE
WARD BLAKE
MILLER CLARK
SMITH JONES
ADAMS JONESWe'll compare putting the condition that removes JONES in two places. First, put it in WHERE.
SELECT LEVEL, RPAD(LPAD(' ', 2 * (LEVEL - 1)) || ENAME, 16) AS TREE FROM EMP WHERE ENAME <> 'JONES' START WITH MGR IS NULL CONNECT BY PRIOR EMPNO = MGR ORDER SIBLINGS BY ENAME; LEVEL TREE
---------- ----------------------------------------------------------------
1 KING
2 BLAKE
3 ALLEN
3 JAMES
3 MARTIN
3 TURNER
3 WARD
2 CLARK
3 MILLER
3 FORD
4 SMITH
3 SCOTT
4 ADAMSThis time, attach it to CONNECT BY with AND.
SELECT LEVEL, RPAD(LPAD(' ', 2 * (LEVEL - 1)) || ENAME, 16) AS TREE FROM EMP START WITH MGR IS NULL CONNECT BY PRIOR EMPNO = MGR AND ENAME <> 'JONES' ORDER SIBLINGS BY ENAME; LEVEL TREE
---------- ----------------------------------------------------------------
1 KING
2 BLAKE
3 ALLEN
3 JAMES
3 MARTIN
3 TURNER
3 WARD
2 CLARK
3 MILLER| Condition position | When it is processed | JONES's subordinates FORD·SCOTT·SMITH·ADAMS | Result rows |
|---|---|---|---|
| WHERE | After the whole tree is built | They remain (LEVEL stays 3, 4) | 13 |
| CONNECT BY | While the tree is being built | The path down through JONES is cut, so they drop out too | 9 |
LEVEL <= 2. Put it in WHERE and it filters after building all the way down; put it in CONNECT BY and it doesn't descend to level 3. The result is the same 4 rows either way: KING·BLAKE·CLARK·JONES.EMP doesn't have this, but if we suppose KING's MGR held SMITH's number, it would loop forever: SMITH → FORD → JONES → KING → SMITH …
CONNECT BY NOCYCLE PRIOR EMPNO = MGR, it cuts the link that goes back to a row already passed and produces a result.CONNECT_BY_ISCYCLE is a pseudo column used together with NOCYCLE. It is 1 if a child of the current row is also an ancestor, and 0 otherwise.Tomorrow we cover the self join, which joins the same EMP with two aliases to put an employee and the manager on one row.
START WITH … CONNECT BY, to pick rows.Click a choice to reveal the answer and explanation.
Question 1
In SELECT LEVEL, ENAME FROM EMP START WITH ENAME = 'SMITH' CONNECT BY PRIOR MGR = EMPNO;, which employee has LEVEL 3? (SMITH's manager is FORD, FORD's manager is JONES, and JONES's manager is KING.)
Question 2
How many rows does SELECT ENAME FROM EMP START WITH MGR IS NULL CONNECT BY PRIOR EMPNO = MGR AND ENAME <> 'JONES'; return? (Below JONES are 4 people: FORD, SCOTT, SMITH, ADAMS, and EMP has 14 employees.)
Question 3
What is the result of SELECT COUNT(*) FROM EMP WHERE CONNECT_BY_ISLEAF = 1 START WITH MGR IS NULL CONNECT BY PRIOR EMPNO = MGR;? (The employees with subordinates are the 6: KING, BLAKE, CLARK, JONES, FORD, SCOTT.)
Question 4
Which statement about ORDER SIBLINGS BY ENAME in a hierarchical query is correct?
Question 5
When expanding with START WITH MGR IS NULL CONNECT BY PRIOR EMPNO = MGR, what is the SYS_CONNECT_BY_PATH(ENAME, '/') value on ADAMS's row? (ADAMS's manager is SCOTT, SCOTT's manager is JONES, and JONES's manager is KING.)