我有一个如图所示的表格,想要从中创建一个树形层次结构。
尝试使用oracle sql执行此操作。
答案 0 :(得分:0)
我建议你改变你的表结构:
emp_id emp_name emp_emp_id (boss of emp_id)
1 BigBoss NULL
2 Boss 1
3 Emp1 2
4 Emp2 2
您可以通过Oracle KeyWord轻松使用连接来恢复层次结构树。 Doc Here => http://docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm
答案 1 :(得分:0)
让我们以SCOTT.EMP
表为例创建层次结构。
SQL> SELECT empno,
2 level,
3 Lpad(ename,LENGTH(ename) + LEVEL * 10 - 10,'-') tree,
4 job,
5 mgr
6 FROM emp
7 START WITH mgr IS NULL
8 CONNECT BY PRIOR empno = mgr
9 /
EMPNO LEVEL TREE JOB MGR
---------- ---------- ----------------------------------- --------- ----------
7839 1 KING PRESIDENT
7566 2 ----------JONES MANAGER 7839
7788 3 --------------------SCOTT ANALYST 7566
7876 4 ------------------------------ADAMS CLERK 7788
7902 3 --------------------FORD ANALYST 7566
7369 4 ------------------------------SMITH CLERK 7902
7698 2 ----------BLAKE MANAGER 7839
7499 3 --------------------ALLEN SALESMAN 7698
7521 3 --------------------WARD SALESMAN 7698
7654 3 --------------------MARTIN SALESMAN 7698
7844 3 --------------------TURNER SALESMAN 7698
7900 3 --------------------JAMES CLERK 7698
7782 2 ----------CLARK MANAGER 7839
7934 3 --------------------MILLER CLERK 7782
14 rows selected.
SQL>
要理解三件重要事项,START WITH
,CONNECT BY PRIOR
和LEVEL
。
START WITH - 指定层次结构的根。确定从哪里开始解析。
先前连接 - 这解释了父母和孩子之间的关系。先前连接empno = mgr
意味着我们正在从top to bottom
穿越。反转它意味着bottom to top
。
LEVEL - 它就像一个伪列,显示层次结构中特定行的级别或等级。
答案 2 :(得分:0)
您需要具有父子层次结构才能执行该操作。我使用HR
默认架构来执行此查询:
with t(val, lvl) as (
select sys_connect_by_path(employee_id, '/'), level lvl
from employees
start with manager_id is null
connect by manager_id = prior employee_id
), t_corr(bigboss, boss, employee) as (
select case
when lvl > 1 then
substr(val, instr(val, '/', 1, 1) + 1, instr(val, '/', 1, 2) - 1 - instr(val, '/', 1, 1))
else
substr(val, instr(val, '/', 1, 1) + 1)
end bigboss
, case
when lvl = 1 then null
when lvl = 2 then
substr(val, instr(val, '/', 1, 2) + 1)
else
substr(val, instr(val, '/', 1, 2) + 1, instr(val, '/', 1, 3) - 1 - instr(val, '/', 1, 2))
end boss
, case
when lvl in (1, 2) then null
else substr(val, instr(val, '/', 1, 3) + 1)
end employee
from t
where lvl < 4
)
select e1.last_name || ' ' || e1.first_name bigboss
, e2.last_name || ' ' || e2.first_name boss
, e3.last_name || ' ' || e3.first_name employee
from t_corr
, employees e1
, employees e2
, employees e3
where t_corr.bigboss = e1.employee_id(+)
and t_corr.boss = e2.employee_id(+)
and t_corr.employee = e3.employee_id(+)
/
BIGBOSS BOSS EMPLOYEE
-------------------- -------------------- --------------------
King Steven
King Steven Kochhar Neena
King Steven Kochhar Neena Greenberg Nancy
King Steven Kochhar Neena Whalen Jennifer
King Steven Kochhar Neena Higgins Shelley
King Steven De Haan Lex
King Steven De Haan Lex Hunold Alexander
King Steven Raphaely Den
...
King Steven Fripp Adam Atkinson Mozhe
King Steven Fripp Adam Marlow James
King Steven Fripp Adam Olson TJ
29 rows selected.
如果您想从表中创建层次结构:
with t(a, b, c, d, e) as (
select 'a', 'b', 'c', 'd', 'e1' from dual union all
select 'a', 'b', 'c', 'd', 'e2' from dual union all
select 'a', 'b', 'c', 'd', 'e3' from dual union all
select 'a', 'b', 'c', 'd', 'e4' from dual union all
select 'a', 'b', 'c', 'd', 'e5' from dual union all
select 'a', 'b', 'c', 'd', 'e6' from dual union all
select 'a', 'b', 'c', 'd', 'e7' from dual union all
select 'a', 'b', 'c', 'd', 'e8' from dual
), tt (a, b, c, d, e) as (
select a, lpad(b, 4, '-'), lpad(c, 8, '-'), lpad(d, 12, '-'), lpad(e, 16, '-') from t
)
select unique dd
from tt
unpivot(
dd for col1 in (a, b, c, d, e)
)
order by 1
DD
--------------------
a
---b
-------c
-----------d
--------------e1
--------------e2
--------------e3
--------------e4
--------------e5
--------------e6
--------------e7
--------------e8