正常的分层方法:
select *
into emp
from
(values
(1, 'President', NULL),
(2, 'Vice President', 1),
(3, 'CEO', 2),
(4, 'CTO', 2),
(5, 'Group Project Manager', 4),
(6, 'Project Manager 1', 5),
(7, 'Project Manager 2', 5),
(8, 'Team Leader 1', 6),
(9, 'Software Engineer 1', 8),
(10, 'Software Engineer 2', 8),
(11, 'Test Lead 1', 6),
(12, 'Tester 1', 11),
(13, 'Tester 2', 11),
(14, 'Team Leader 2', 7),
(15, 'Software Engineer 3', 14),
(16, 'Software Engineer 4', 14),
(17, 'Test Lead 2', 7),
(18, 'Tester 3', 17),
(19, 'Tester 4', 17),
(20, 'Tester 5', 17)
) as x(emp_id, emp_name, mgr_id)
询问:
with recursive org(emp_id, emp_name, emp_level, mgr_id, sort) as
(
select
a.emp_id, a.emp_name, 0, a.mgr_id,
a.emp_name
from emp a
where a.mgr_id is null
union all
select
b.emp_id, b.emp_name, emp_level + 1, b.mgr_id,
sort || ' : ' || b.emp_name
from emp b
join org on org.emp_id = b.mgr_id
)
select
emp_id, repeat(' ', emp_level * 2) || emp_name as emp_name, sort
from org
order by sort
输出:
emp_id | emp_name | sort
--------+---------------------------------+--------------------------------------------------------------------------------------------------------------------
1 | President | President
2 | Vice President | President : Vice President
3 | CEO | President : Vice President : CEO
4 | CTO | President : Vice President : CTO
5 | Group Project Manager | President : Vice President : CTO : Group Project Manager
6 | Project Manager 1 | President : Vice President : CTO : Group Project Manager : Project Manager 1
8 | Team Leader 1 | President : Vice President : CTO : Group Project Manager : Project Manager 1 : Team Leader 1
9 | Software Engineer 1 | President : Vice President : CTO : Group Project Manager : Project Manager 1 : Team Leader 1 : Software Engineer 1
10 | Software Engineer 2 | President : Vice President : CTO : Group Project Manager : Project Manager 1 : Team Leader 1 : Software Engineer 2
11 | Test Lead 1 | President : Vice President : CTO : Group Project Manager : Project Manager 1 : Test Lead 1
12 | Tester 1 | President : Vice President : CTO : Group Project Manager : Project Manager 1 : Test Lead 1 : Tester 1
13 | Tester 2 | President : Vice President : CTO : Group Project Manager : Project Manager 1 : Test Lead 1 : Tester 2
7 | Project Manager 2 | President : Vice President : CTO : Group Project Manager : Project Manager 2
14 | Team Leader 2 | President : Vice President : CTO : Group Project Manager : Project Manager 2 : Team Leader 2
15 | Software Engineer 3 | President : Vice President : CTO : Group Project Manager : Project Manager 2 : Team Leader 2 : Software Engineer 3
16 | Software Engineer 4 | President : Vice President : CTO : Group Project Manager : Project Manager 2 : Team Leader 2 : Software Engineer 4
17 | Test Lead 2 | President : Vice President : CTO : Group Project Manager : Project Manager 2 : Test Lead 2
18 | Tester 3 | President : Vice President : CTO : Group Project Manager : Project Manager 2 : Test Lead 2 : Tester 3
19 | Tester 4 | President : Vice President : CTO : Group Project Manager : Project Manager 2 : Test Lead 2 : Tester 4
20 | Tester 5 | President : Vice President : CTO : Group Project Manager : Project Manager 2 : Test Lead 2 : Tester 5
(20 rows)
现在让我们覆盖对 Group Project Managers 的排序,让项目经理 2 在项目经理 1 之前,项目经理 1 在项目经理 2 之后。让我们也让测试人员 4 在测试人员 3 之前,测试人员 3 在测试人员 4 之后
alter table emp add column order_override int null;
update emp set order_override = 1 where emp_id = 7; -- PM 2
update emp set order_override = 2 where emp_id = 6; -- PM 1
update emp set order_override = 1 where emp_id = 19; -- Tester 4
update emp set order_override = 2 where emp_id = 18; -- Tester 3
询问:
with recursive org(emp_id, emp_name, emp_level, mgr_id, sort) as
(
select
a.emp_id, a.emp_name, 0, a.mgr_id,
a.emp_name
from emp a
where a.mgr_id is null
union all
select
b.emp_id, b.emp_name, emp_level + 1, b.mgr_id,
sort || ' : ' || coalesce( lpad(order_override::text, 10, '0'), b.emp_name )
from emp b
join org on org.emp_id = b.mgr_id
)
select
emp_id, repeat(' ', emp_level * 2) || emp_name as emp_name, sort
from org
order by sort
输出:
emp_id | emp_name | sort
--------+---------------------------------+-------------------------------------------------------------------------------------------------------------
1 | President | President
2 | Vice President | President : Vice President
3 | CEO | President : Vice President : CEO
4 | CTO | President : Vice President : CTO
5 | Group Project Manager | President : Vice President : CTO : Group Project Manager
7 | Project Manager 2 | President : Vice President : CTO : Group Project Manager : 0000000001
14 | Team Leader 2 | President : Vice President : CTO : Group Project Manager : 0000000001 : Team Leader 2
15 | Software Engineer 3 | President : Vice President : CTO : Group Project Manager : 0000000001 : Team Leader 2 : Software Engineer 3
16 | Software Engineer 4 | President : Vice President : CTO : Group Project Manager : 0000000001 : Team Leader 2 : Software Engineer 4
17 | Test Lead 2 | President : Vice President : CTO : Group Project Manager : 0000000001 : Test Lead 2
19 | Tester 4 | President : Vice President : CTO : Group Project Manager : 0000000001 : Test Lead 2 : 0000000001
18 | Tester 3 | President : Vice President : CTO : Group Project Manager : 0000000001 : Test Lead 2 : 0000000002
20 | Tester 5 | President : Vice President : CTO : Group Project Manager : 0000000001 : Test Lead 2 : Tester 5
6 | Project Manager 1 | President : Vice President : CTO : Group Project Manager : 0000000002
8 | Team Leader 1 | President : Vice President : CTO : Group Project Manager : 0000000002 : Team Leader 1
9 | Software Engineer 1 | President : Vice President : CTO : Group Project Manager : 0000000002 : Team Leader 1 : Software Engineer 1
10 | Software Engineer 2 | President : Vice President : CTO : Group Project Manager : 0000000002 : Team Leader 1 : Software Engineer 2
11 | Test Lead 1 | President : Vice President : CTO : Group Project Manager : 0000000002 : Test Lead 1
12 | Tester 1 | President : Vice President : CTO : Group Project Manager : 0000000002 : Test Lead 1 : Tester 1
13 | Tester 2 | President : Vice President : CTO : Group Project Manager : 0000000002 : Test Lead 1 : Tester 2
(20 rows)
在数据投影中没有排序列:
with recursive org(emp_id, emp_name, emp_level, mgr_id, sort) as
(
select
a.emp_id, a.emp_name, 0, a.mgr_id,
a.emp_name
from emp a
where a.mgr_id is null
union all
select
b.emp_id, b.emp_name, emp_level + 1, b.mgr_id,
sort || ' : ' || coalesce( lpad(order_override::text, 10, '0'), b.emp_name )
from emp b
join org on org.emp_id = b.mgr_id
)
select
emp_id, repeat(' ', emp_level * 2) || emp_name as emp_name
from org
order by sort
输出:
emp_id | emp_name
--------+---------------------------------
1 | President
2 | Vice President
3 | CEO
4 | CTO
5 | Group Project Manager
7 | Project Manager 2
14 | Team Leader 2
15 | Software Engineer 3
16 | Software Engineer 4
17 | Test Lead 2
19 | Tester 4
18 | Tester 3
20 | Tester 5
6 | Project Manager 1
8 | Team Leader 1
9 | Software Engineer 1
10 | Software Engineer 2
11 | Test Lead 1
12 | Tester 1
13 | Tester 2
(20 rows)
项目经理 2 在项目经理 1 之前。测试人员 4 在测试人员 3 之前
如果存在 order_override(non-null),则该技术在于 b.name 的数字文本替换:
sort || ' : ' || coalesce( lpad(order_override::text, 10, '0'), b.emp_name )
上面的代码是Postgres,要转换成Sql Server,去掉单词,RECURSIVE
改成REPEAT
,到。REPLICATE
||
+
相当于...
lpad(order_override::text, 10, '0')
...是:
RIGHT( REPLICATE('0',10) + CONVERT(VARCHAR, order_override), 10)