Oracle.start with … connect by [… and] prior…order siblings by …
在整個BOM中,動態地指定修改其中某一層,則其子項隨其修改項做出對應變更。
EMPLOYEE_ID |
MANAGER_ID |
NAME |
CREATE_DATE |
LEVEL |
100 |
NULL |
King |
2000-12-12 |
1 |
148 |
100 |
Cambrault |
2009-01-01 |
2 |
172 |
148 |
Bates |
2010-11-01 |
3 |
169 |
148 |
Bloom |
2011-08-21 |
3 |
170 |
148 |
Fox |
2009-03-01 |
3 |
173 |
148 |
Kumar |
2009-06-11 |
3 |
168 |
148 |
Ozer |
2009-10-07 |
3 |
171 |
148 |
Smith |
2012-05-01 |
3 |
102 |
100 |
DeHaan |
2012-01-01 |
2 |
103 |
102 |
Hunold |
2009-12-03 |
3 |
105 |
103 |
Austin |
2011-01-01 |
4 |
104 |
103 |
Ernst |
2011-11-01 |
4 |
107 |
103 |
Lorentz |
2012-11-01 |
4 |
106 |
103 |
Pataballa |
2009-01-01 |
4 |
147 |
100 |
Errazuriz |
2010-11-23 |
2 |
166 |
147 |
Ande |
2010-12-14 |
3 |
167 |
147 |
Banda |
2009-09-01 |
3 |
--create table create table kol_employees_tmp ( employee_id number(5) not null, name varchar2(50) not null, manager_id number(5) , create_date date ) --insert data begin insert into kol_employees_tmp(employee_id, name, manager_id, create_date) values(172,'Bates',148,to_date('2010-11-01', 'YYYY-MM-DD')); insert into kol_employees_tmp(employee_id, name, manager_id, create_date) values(169,'Bloom',148,to_date('2011-08-21', 'YYYY-MM-DD')); insert into kol_employees_tmp(employee_id, name, manager_id, create_date) values(173,'Kumar',148,to_date('2009-06-11', 'YYYY-MM-DD')); insert into kol_employees_tmp(employee_id, name, manager_id, create_date) values(168,'Ozer',148,to_date('2009-10-07', 'YYYY-MM-DD')); insert into kol_employees_tmp(employee_id, name, manager_id, create_date) values(100,'King',null,to_date('2009-01-01', 'YYYY-MM-DD')); insert into kol_employees_tmp(employee_id, name, manager_id, create_date) values(148,'Cambrault',100,to_date('2009-01-01', 'YYYY-MM-DD')); insert into kol_employees_tmp(employee_id, name, manager_id, create_date) values(170,'Fox',148,to_date('2009-03-01', 'YYYY-MM-DD')); insert into kol_employees_tmp(employee_id, name, manager_id, create_date) values(147,'Errazuriz',100,to_date('2010-11-23', 'YYYY-MM-DD')); insert into kol_employees_tmp(employee_id, name, manager_id, create_date) values(167,'Banda',147,to_date('2009-09-01', 'YYYY-MM-DD')); insert into kol_employees_tmp(employee_id, name, manager_id, create_date) values(103,'Hunold',102,to_date('2009-12-03', 'YYYY-MM-DD')); insert into kol_employees_tmp(employee_id, name, manager_id, create_date) values(166,'Ande',147,to_date('2010-12-14', 'YYYY-MM-DD')); insert into kol_employees_tmp(employee_id, name, manager_id, create_date) values(171,'Smith',148,to_date('2012-05-01', 'YYYY-MM-DD')); insert into kol_employees_tmp(employee_id, name, manager_id, create_date) values(102,'DeHaan',100,to_date('2012-01-01', 'YYYY-MM-DD')); insert into kol_employees_tmp(employee_id, name, manager_id, create_date) values(107,'Lorentz',103,to_date('2012-11-01', 'YYYY-MM-DD')); insert into kol_employees_tmp(employee_id, name, manager_id, create_date) values(106,'Pataballa',103,to_date('2009-01-01', 'YYYY-MM-DD')); insert into kol_employees_tmp(employee_id, name, manager_id, create_date) values(105,'Austin',103,to_date('2011-01-01', 'YYYY-MM-DD')); insert into kol_employees_tmp(employee_id, name, manager_id, create_date) values(104,'Ernst',103,to_date('2011-11-01', 'YYYY-MM-DD')); end;
--create temp table with kol_employees_tmp as( select '2010-11-01' create_date, 172 employee_id, 148 manager_id, 'Bates' name from dual union all select null create_date, 169 employee_id, 148 manager_id, 'Bloom' name from dual union all select null create_date, 173 employee_id, 148 manager_id, 'Kumar' name from dual union all select null create_date, 168 employee_id, 148 manager_id, 'Ozer' name from dual union all select '2000-04-04' create_date, 100 employee_id, null manager_id, 'King' name from dual union all select null create_date, 148 employee_id, 100 manager_id, 'Cambrault' name from dual union all select null create_date, 170 employee_id, 148 manager_id, 'Fox' name from dual union all select '2010-11-23' create_date, 147 employee_id, 100 manager_id, 'Errazuriz' name from dual union all select '2009-09-01' create_date, 167 employee_id, 147 manager_id, 'Banda' name from dual union all --select '2009-12-03' create_date, 103 employee_id, 102 manager_id, 'Hunold' name from dual select '2013-12-03' create_date, 103 employee_id, 102 manager_id, 'Hunold' name from dual union all select null create_date, 166 employee_id, 147 manager_id, 'Ande' name from dual union all select null create_date, 171 employee_id, 148 manager_id, 'Smith' name from dual union all select '2012-01-01' create_date, 102 employee_id, 100 manager_id, 'DeHaan' name from dual union all select null create_date, 107 employee_id, 103 manager_id, 'Lorentz' name from dual union all select '2009-01-01' create_date, 106 employee_id, 103 manager_id, 'Pataballa' name from dual union all --select '2011-01-01' create_date, 105 employee_id, 103 manager_id, 'Austin' name from dual select '2018-01-01' create_date, 105 employee_id, 103 manager_id, 'Austin' name from dual union all select null create_date, 104 employee_id, 103 manager_id, 'Ernst' name from dual ) , condition_list as( select emp.employee_id, emp.manager_id, emp.name, emp.create_date, level level_id from kol_employees_tmp emp where 1=1 and emp.create_date is not null --start with emp.employee_id = :p_root_item -- itme no start with emp.employee_id = 100 -- itme no connect by prior emp.employee_id = emp.manager_id ) , redo_employees as( select t2.employee_id, t2.manager_id, t2.name, t2.create_date, t2.parent_create_date, t2.level_id from( select t1.employee_id, t1.manager_id, t1.name, t1.create_date, t1.parent_create_date, t1.level_id, --t1.path, --t1.isleaf, row_number() over(partition by t1.employee_id, t1.manager_id order by t1.parent_create_date desc) maxover_seq from( select emp.employee_id, emp.manager_id, emp.name, emp.create_date, connect_by_root(emp.create_date) parent_create_date, level level_id --sys_connect_by_path(emp.employee_id || decode(emp.manager_id,null, '', '*' || emp.manager_id), '/') path, --connect_by_isleaf isleaf from kol_employees_tmp emp where 1=1 --and emp.employee_id in( 102, 105, 106, 147, 167,172) -- start with emp.employee_id = 100 start with emp.employee_id in(select cl.employee_id from condition_list cl) --in( 102, 105, 106, 147, 167,172, 103) connect by prior emp.employee_id = emp.manager_id --order siblings by emp.name ) t1 ) t2 where 1=1 and t2.maxover_seq = 1 --------------------- union all select ket2.employee_id, ket2.manager_id, ket2.name, ket2.create_date, ket2.create_date parent_create_date, level level_id from kol_employees_tmp ket2 --start with ket2.employee_id = decode( (select count(1) from condition_list where employee_id = :p_root_item), 0, :p_root_item, '-1') -- itme no start with ket2.employee_id = decode( (select count(1) from condition_list where employee_id = 100), 0, 100, '-1') -- itme no connect by ket2.employee_id not in(select cl.employee_id from condition_list cl) --in( 102, 105, 106, 147, 167,172, 103) -- break level and prior ket2.employee_id = ket2.manager_id ) --query process tables select emp.employee_id, emp.manager_id, emp.name, emp.create_date, emp.parent_create_date, level level_id from redo_employees emp --start with emp.employee_id = :p_root_item -- itme no start with emp.employee_id = 100 -- itme no connect by prior emp.employee_id = emp.manager_id order siblings by emp.name;