Presentation is loading. Please wait.

Presentation is loading. Please wait.

Accessing Hierarchical Data in Oracle Carol-Lee Erikson Tutch

Similar presentations


Presentation on theme: "Accessing Hierarchical Data in Oracle Carol-Lee Erikson Tutch"— Presentation transcript:

1 Accessing Hierarchical Data in Oracle Carol-Lee Erikson Tutch

2 Hierarchically Structured Data Items at different levels are similar Arbitrary number of levels Examples – Personnel Officer Manager Contributor – Manufacturing Product Assembly Part

3 Representing a Hierarchy Items have a Parent-Child relationship Hierarchy can be visualized as a Tree Item is called a Node Connections btw nodes are Links Node has 0 or 1 parent Node w/o parent is a Root Node has 0 to N children Node w/o children is a Leaf

4 Level 1 Level 2 Level 3 Level 4 Level 5 Hierarchy Tree

5 ER Diagram

6 Structure for Sample Data CREATE TABLE emp ( emp_id NUMBER(5) NOT NULL, emp_name VARCHAR2(30) NOT NULL, mgr_emp_id NUMBER(5), dept_cd VARCHAR2(6), sal NUMBER(9,2), hire_dt DATE NOT NULL ); CREATE UNIQUE INDEX emp_pk ON emp ( emp_id ); ALTER TABLE emp ADD CONSTRAINT emp_pk PRIMARY KEY ( emp_id ) USING INDEX emp_pk; CREATE INDEX emp_f1 ON emp ( mgr_emp_id ASC ); ALTER TABLE emp ADD CONSTRAINT emp_f1 FOREIGN KEY ( mgr_emp_id ) REFERENCES emp ( emp_id );

7 Sample Data SELECT * FROM emp ORDER BY emp_id; EMP_IDEMP_NAMEMGR_EMP_IDDEPT_CDSALHIRE_DT 10BarbaraPRES300,00001-Jan John10PRES50,00003-Jan Edward10SALES100,00001-Feb Josh12SALES70,00001-Mar Beth10IT150,00001-May Rich14IT90,00001-Jul GeorgeFIN200,00001-Feb Barby12SALES100,00001-Apr Michelle14IT70,00002-Jan Tom14IT80,00001-Feb John16FIN100,00003-Jan Sam14IT110,00001-Jan Robin28IT60,00001-Jun Jane24FIN60,00001-Feb Mary16FIN70,00001-Mar-2005

8 Sample Data Graph 10 Barbara 16 George 11 John 12 Edward 14 Beth 13 Josh 15 Rich 17 Barby 21 Michelle 22 Tom 24 John 33 Mary 28 Sam 31 Robin 32 Jane

9 Employees & Supervisors SELECT e.emp_id, e.emp_name, m.emp_id AS mgr_id, m.emp_name AS mgr_name FROM emp e JOIN emp m ON e.mgr_emp_id = m.emp_id ORDER BY e.emp_id; EMP_IDEMP_NAMEMGR_IDMGR_NAME 11John10Barbara 12Edward10Barbara 13Josh12Edward 14Beth10Barbara 15Rich14Beth 17Barby12Edward 21Michelle14Beth 22Tom14Beth 24John16George 28Sam14Beth 31Robin28Sam 32Jane24John 33Mary16George

10 … Add Top-Level Supervisors SELECT e.emp_id, e.emp_name, m.emp_id AS mgr_id, m.emp_name AS mgr_name FROM emp e LEFT JOIN emp m ON e.mgr_emp_id = m.emp_id ORDER BY e.emp_id; EMP_IDEMP_NAMEMGR_IDMGR_NAME 10Barbara 11John10Barbara 12Edward10Barbara 13Josh12Edward 14Beth10Barbara 15Rich14Beth 16George 17Barby12Edward 21Michelle14Beth 22Tom14Beth 24John16George 28Sam14Beth 31Robin28Sam 32Jane24John 33Mary16George

11 … Add Supervisor’s Supervisors SELECT e.emp_id, e.emp_name, m1.emp_id AS mgr_id1, m1.emp_name AS gr_name1, m2.emp_id AS mgr_id2, m2.emp_name AS mgr_name2 FROM emp e LEFT JOIN emp m1 ON e.mgr_emp_id = m1.emp_id LEFT JOIN emp m2 ON m1.mgr_emp_id = m2.emp_id ORDER BY e.emp_id; EMP_IDEMP_NAMEMGR_ID1MGR_NAME1MGR_ID2MGR_NAME2 10Barbara 11John10Barbara 12Edward10Barbara 13Josh12Edward10Barbara 14Beth10Barbara 15Rich14Beth10Barbara 16George 17Barby12Edward10Barbara 21Michelle14Beth10Barbara 22Tom14Beth10Barbara 24John16George 28Sam14Beth10Barbara 31Robin28Sam14Beth 32Jane24John16George 33Mary16George

12 All Root Nodes SELECT e.emp_id, e.emp_name FROM emp e WHERE e.mgr_emp_id IS NULL; EMP_IDEMP_NAME 10Barbara 16George

13 All Leaf Nodes SELECT e.emp_id, e.emp_name FROM emp e WHERE e.emp_id NOT IN ( SELECT DISTINCT m.mgr_emp_id FROM emp m WHERE m.mgr_emp_id IS NOT NULL ); EMP_IDEMP_NAME 11John 13Josh 15Rich 21Michelle 22Tom 17Barby 31Robin 32Jane 33Mary

14 Oracle Extensions for Hierarchies CONNECT BY clause – Allows linking w/n same range variable (table alias) – Occurs after WHERE clause – Executes before WHERE clause PRIOR keyword – Indicates how to connect w/ last record retrieved – Can occur on either side of the join – Can be used multiple times START WITH clause – Indicates record(s) to initially retrieve – Optional: w/o, initially starts w/ all records

15 Basic Hierarchy Query SELECT e.emp_id, e.emp_name, e.mgr_emp_id FROM emp e START WITH e.mgr_emp_id IS NULL CONNECT BY PRIOR e.emp_id = e.mgr_emp_id; EMP_IDEMP_NAMEMGR_EMP_ID 10Barbara 11John10 12Edward10 13Josh12 17Barby12 14Beth10 15Rich14 21Michelle14 22Tom14 28Sam14 31Robin28 16George 24John16 32Jane24 33Mary16

16 Adding the Manager Name SELECT e.emp_id AS "E ID", e.emp_name AS "Employee", m.emp_id AS "M ID", m.emp_name AS "Manager" FROM ( SELECT e.emp_id, e.mgr_emp_id FROM emp e START WITH e.mgr_emp_id IS NULL CONNECT BY PRIOR e.emp_id = e.mgr_emp_id ) h JOIN emp e ON h.emp_id = e.emp_id JOIN emp m ON h.mgr_emp_id = m.emp_id ORDER BY e.emp_id; E IDEmployeeM IDManager 11John10Barbara 12Edward10Barbara 13Josh12Edward 14Beth10Barbara 15Rich14Beth 17Barby12Edward 21Michelle14Beth 22Tom14Beth 24John16George 28Sam14Beth 31Robin28Sam 32Jane24John 33Mary16George

17 Start w/ any Record Set SELECT e.emp_id, e.emp_name, e.mgr_emp_id FROM emp e START WITH e.emp_name = 'Beth‘ CONNECT BY e.mgr_emp_id = PRIOR e.emp_id; EMP_IDEMP_NAMEMGR_EMP_ID 14Beth10 15Rich14 21Michelle14 22Tom14 28Sam14 31Robin28

18 Indicating LEVEL SELECT LEVEL, e.emp_id, e.emp_name, e.mgr_emp_id FROM emp e START WITH e.emp_name = 'Beth‘ CONNECT BY PRIOR e.emp_id = e.mgr_emp_id; LEVELEMP_IDEMP_NAMEMGR_EMP_ID 114Beth10 215Rich14 221Michelle14 222Tom14 228Sam14 331Robin28

19 Use Functions on LEVEL SELECT MAX(level) AS maxlevel FROM emp e START WITH e.mgr_emp_id IS NULL CONNECT BY PRIOR e.emp_id = e.mgr_emp_id; MAXLEVEL 4

20 Aggregate on LEVEL SELECT level, COUNT ( emp_id ) FROM emp e START WITH e.mgr_emp_id IS NULL CONNECT BY PRIOR e.emp_id = e.mgr_emp_id GROUP BY level; LEVELCOUNT ( EMP_ID )

21 Indenting Dependents SELECT LPAD ( ' ', 3 * ( level - 1 ) ) || e.emp_name AS "Employee", level, e.emp_id, e.mgr_emp_id FROM emp e START WITH e.mgr_emp_id IS NULL CONNECT BY PRIOR e.emp_id = e.mgr_emp_id; EmployeeLEVELEMP_IDMGR_EMP_ID Barbara110 John21110 Edward21210 Josh31312 Barbara31712 Beth21410 Rich31514 Michelle32114 Tom32214 Sam32814 Robin43128 George116 John22416 Jane33224 Mary23316

22 Filter a Hierarchy SELECT LPAD ( ' ', 3 * ( level - 1 ) ) || e.emp_name AS "Employee", level, e.emp_id, e.mgr_emp_id FROM emp e WHERE e.hire_dt < '1-Jan-2004' START WITH e.mgr_emp_id IS NULL CONNECT BY PRIOR e.emp_id = e.mgr_emp_id; EmployeeLEVELEMP_IDMGR_EMP_ID Barbara110 John21110 Edward21210 Beth21410 Rich31514 Michelle32114 Sam32814 George116 John22416

23 Top N Levels of Hierarchy SELECT LPAD ( ' ', 3 * ( level - 1 ) ) || e.emp_name AS "Employee", level, e.emp_id, e.mgr_emp_id FROM emp e WHERE level <= 2 START WITH e.mgr_emp_id IS NULL CONNECT BY PRIOR e.emp_id = e.mgr_emp_id; EmployeeLEVELEMP_IDMGR_EMP_ID Barbara110 John21110 Edward21210 Beth21410 George116 John22416 Mary23316

25 Sorting: The SIBLINGS Clause SELECT LPAD ( ' ', 3 * ( level - 1 ) ) || e.emp_name AS "Employee", level, e.emp_id, e.mgr_emp_id FROM emp e START WITH e.mgr_emp_id IS NULL CONNECT BY PRIOR e.emp_id = e.mgr_emp_id ORDER SIBLINGS BY emp_name; EmployeeLEVELEMP_IDMGR_EMP_ID Barbara110 Beth21410 Michelle32114 Rich31514 Sam32814 Robin43128 Tom32214 Edward21210 Barby31712 Josh31312 John21110 George116 John22416 Jane33224 Mary23316

26 Display a Path SELECT SUBSTR ( SYS_CONNECT_BY_PATH ( e.emp_name, ' - ' ), 4 ) AS "Employee Path" FROM emp e START WITH e.mgr_emp_id IS NULL CONNECT BY PRIOR e.emp_id = e.mgr_emp_id ORDER SIBLINGS BY emp_name; Employee Path Barbara Barbara - Beth Barbara - Beth - Michelle Barbara - Beth - Rich Barbara - Beth - Sam Barbara - Beth - Sam - Robin Barbara - Beth - Tom Barbara - Edward Barbara - Edward - Barby Barbara - Edward - Josh Barbara - John George George - John George - John - Jane George - Mary

27 The Root for Each Node SELECT e.emp_id, e.emp_name AS "Employee", CONNECT_BY_ROOT e.emp_name AS "Top Dog" FROM emp e START WITH e.mgr_emp_id IS NULL CONNECT BY PRIOR e.emp_id = e.mgr_emp_id; EMP_IDEmployeeTop Dog 10Barbara 11JohnBarbara 12EdwardBarbara 13JoshBarbara 17Barbara 14BethBarbara 15RichBarbara 21MichelleBarbara 22TomBarbara 28SamBarbara 31RobinBarbara 16George 24JohnGeorge 32JaneGeorge 33MaryGeorge

28 Has a Connection to SELECT * FROM emp e WHERE e.emp_name = 'Beth' START WITH e.emp_name = 'Robin‘ CONNECT BY e.emp_id = PRIOR e.mgr_emp_id; EMP_IDEMP_NAMEMGR_EMP_IDDEPT_CDSALHIRE_DT 14Beth10IT150,00001-May-2001

29 Summng Dependent Info SELECT t2.emp_id, t2.emp_name, t2.sal, ( SELECT SUM ( t1.sal ) FROM emp t1 START WITH t1.emp_id = t2.emp_id CONNECT BY t1.mgr_emp_id = PRIOR t1.emp_id ) AS sum_salary FROM emp t2; EMP_IDEMP_NAMESALSUM_SALARY 10Barbara300,0001,180,000 11John50,000 12Edward100,000270,000 13Josh70,000 14Beth150,000560,000 15Rich90,000 21Michelle70,000 22Tom80,000 17Barby100,000 28Sam110,000170,000 31Robin60,000 16George200,000430,000 24John100,000160,000 32Jane60,000 33Mary70,000

30 Cycles in a Hierarchy UPDATE emp e SET e.mgr_emp_id = 22 WHERE e.emp_id = 10; SELECT LPAD ( ' ', 3 * ( level - 1 ) ) || e.emp_name AS "Employee", level, e.emp_id, e.mgr_emp_id FROM emp e START WITH e.mgr_emp_id = 10 CONNECT BY PRIOR e.emp_id = e.mgr_emp_id; 17:08:52 Error: ORA-01436: CONNECT BY loop in user data

31 Running w/ Errors SELECT LPAD ( ' ', 3 * ( level - 1 ) ) || e.emp_name AS "Employee", level, e.emp_id, e.mgr_emp_id FROM emp e START WITH e.mgr_emp_id = 10 CONNECT BY NOCYCLE PRIOR e.emp_id = e.mgr_emp_id; EmployeeLEVELEMP_IDMGR_EMP_ID John11110 Edward11210 Josh21312 Barby21712 Beth11410 Rich21514 Michelle22114 Tom22214 Barbara31022 John41110 Edward41210 Josh51312 Barby51712 Sam22814 Robin33128

32 Trapping Cycle Errors SELECT e.emp_id, e.emp_name, CONNECT_BY_ISCYCLE FROM emp e START WITH e.mgr_emp_id = 10 CONNECT BY NOCYCLE PRIOR e.emp_id = e.mgr_emp_id; ROLLBACK; EMP_IDEMP_NAMECONNECT_BY_ISCYCLE 11John0 12Edward0 13Josh0 17Barby0 14Beth0 15Rich0 21Michelle0 22Tom0 10Barbara1 11John0 12Edward0 13Josh0 17Barby0 28Sam0 31Robin0

33 Finding Leaf Nodes SELECT e.emp_id, e.emp_name FROM emp e WHERE CONNECT_BY_ISLEAF = 1 START WITH e.mgr_emp_id IS NULL CONNECT BY PRIOR e.emp_id = e.mgr_emp_id; EMP_IDEMP_NAME 11John 13Josh 17Barby 15Rich 21Michelle 22Tom 31Robin 32Jane 33Mary

34 Source of Information Mastering Oracle SQL, 2nd Edition Sanjay MishraSanjay Mishra & Alan Beaulieu O'Reilly Media, Inc., 2004 ISBN-13: pages

35 Counter SELECT level x FROM dual CONNECT BY level <= 100; X …

36 Additional Tricks w/ CONNECT BY Finding potential flights using an INTERSECT of 2 CONNECT BY SQL Pocket Guide, 2nd Edition By: Jonathan GennickJonathan Gennick Publisher : O'Reilly Media, Inc. Pub. Date: April 17, 2006 Print ISBN-13: Pages in Print Edition: 192


Download ppt "Accessing Hierarchical Data in Oracle Carol-Lee Erikson Tutch"

Similar presentations


Ads by Google