分层查询 - 限制每个级别的元素数量
Hierarchical query - limiting number of elements per level
我正在使用 Oracle DBMS,我有一个关于分层查询的问题。
我正在使用分层 SQL 查询为我的部门创建一个组织列表。组织结构分为三个级别,依次是部门经理、部门经理和团队成员。
我目前的查询是:
SELECT level, employee_number, name, manager, department, phone
FROM employee_table
START WITH manager is null
CONNECT BY PRIOR employee_number = manager;
此查询生成一个分层列表,其中部门经理处于一级,每个部门经理处于二级,团队成员处于三级。总的来说,只有一个部门经理,三个科长,30个组员。
问题:我的要求是将列表中每个级别的员工数量限制为最多三名员工。前两级没问题,因为只有一个部门经理和三个科长(科长永远不会超过三个),但我现在三级有30个团队成员(每个科长管理10个团队成员) ).我的目标是在第 3 级有三个团队成员,在第 4 级有三个团队成员,在第 5 级有三个团队成员,等等。团队成员的顺序无关紧要,所以哪个团队成员在3 级,哪些团队成员处于 4 级,等等
我宁愿避免为了实现这个目标而将团队成员的经理设置为另一个团队成员的 employee_number。我可以在 employee_table 中创建另一个名为 "org_list_parent" 的列,并指出一个团队成员的 "org_list_parent" 是另一个团队成员的 employee_number,但我更愿意尽可能避免这样做。
有人对这个问题有什么想法吗?
提前谢谢你。
更新:
使用 mathguy 的查询,我能够获得最接近我想要达到的结果的输出。但是,如果可能的话,我想对输出进行一些调整。我正在使用此列表在 Oracle Apex 中构建组织结构图,并使用 mathguy 的 table 和查询,我得到以下输出:
这与我要制作的视觉效果非常接近。 “每个级别 3 个团队成员”背后的原因是试图防止图表在水平方向上过大。但是,如果你向左看,比如员工1104、1105、1106在1103下面,员工1107在1106下面。最好员工1104在1101下面,员工1105在1102下面,员工1106在1103下面,员工 1107 位于 1104 下方。是否有任何方法可以编辑查询以直观地生成该结果?
更新二:
alexgibbs 请求对他建议的两个不同查询的反馈作为我的问题的解决方案。以下是他的第一个查询:
SELECT CASE WHEN LEVEL < 3
THEN LEVEL
ELSE 3 + FLOOR((DENSE_RANK() OVER (PARTITION BY MANAGER ORDER BY
EMPLOYEE_NUMBER ASC ) - 1) / 3) END AS ADJUSTED_LEVEL,
EMPLOYEE_NUMBER, MANAGER
FROM EMPLOYEE_TABLE
START WITH MANAGER IS NULL
CONNECT BY PRIOR EMPLOYEE_NUMBER = MANAGER
ORDER BY 2 ASC, 1 ASC;
以下是此查询在 Oracle Apex 中作为列表的输出:
以下是他的第二个查询:
SELECT
CASE WHEN LEVEL < 3
THEN LEVEL
ELSE 3 + FLOOR((DENSE_RANK() OVER (PARTITION BY MANAGER ORDER BY
EMPLOYEE_NUMBER ASC ) - 1) / 3) END AS ADJUSTED_LEVEL,
EMPLOYEE_NUMBER,
MANAGER,
DEPARTMENT
FROM EMPLOYEE_TABLE
START WITH MANAGER IS NULL
CONNECT BY PRIOR EMPLOYEE_NUMBER = MANAGER
ORDER BY
NVL2(MANAGER,1,0) ASC,
DEPARTMENT ASC,
CASE WHEN LEVEL < 3
THEN LEVEL
ELSE (MOD((DENSE_RANK() OVER (PARTITION BY MANAGER ORDER BY EMPLOYEE_NUMBER
ASC )) - 1,3) + 3) END ASC,
ADJUSTED_LEVEL ASC;
下面是这个查询在 Oracle Apex 中的输出:
注意:已针对问题的更新进行了大量编辑,uncertain/not-tested 具有兼容性的顶点
下面的解决方案只会在第 2 级添加超过第三级的部门经理。但是对于第 3 级以上,如果在部门经理之外如何分配额外级别并不重要,可以仅根据 employee_id
。随着三人组中每个成员的伪下一级直接嵌套在下方的更新,这里是一个示例,根据员工 ID,在一个三人组中分配伪级别和子级别部门。
下面是一个示例数据集和查询。
CREATE TABLE EMPLOYEE_TABLE (
EMPLOYEE_NUMBER NUMBER,
MANAGER NUMBER DEFAULT NULL,
NAME CHARACTER VARYING(64 BYTE),
DEPARTMENT CHARACTER VARYING(64 BYTE),
PHONE CHARACTER VARYING(64 BYTE)
);
--Dept Manager
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (10,NULL, 1);
--Section Managers
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (200,10, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (300,10, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (400,10, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (500,10, 5);
-- Section Employees
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (2010,200, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (2020,200, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (2030,200, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (2040,200, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (2050,200, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (2060,200, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (2070,200, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (2080,200, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (2090,200, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (2100,200, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (3010,300, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (3020,300, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (3030,300, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (3040,300, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (3050,300, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (3060,300, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (3070,300, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (3080,300, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (3090,300, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (3100,300, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (4010,400, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (4020,400, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (4030,400, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (4040,400, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (4050,400, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (4060,400, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (4070,400, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (4080,400, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (4090,400, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (4100,400, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (5010,500, 5);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (5020,500, 5);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (5030,500, 5);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (5040,500, 5);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (5050,500, 5);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (5060,500, 5);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (5070,500, 5);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (5080,500, 5);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (5090,500, 5);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (5100,500, 5);
COMMIT;
已编辑
查询:
SELECT
CASE WHEN LEVEL < 3
THEN LEVEL
ELSE 3 + FLOOR((DENSE_RANK() OVER (PARTITION BY MANAGER ORDER BY EMPLOYEE_NUMBER ASC ) - 1) / 3) END AS ADJUSTED_LEVEL,
EMPLOYEE_NUMBER,
MANAGER,
DEPARTMENT
FROM EMPLOYEE_TABLE
START WITH MANAGER IS NULL
CONNECT BY PRIOR EMPLOYEE_NUMBER = MANAGER
ORDER BY
NVL2(MANAGER,1,0) ASC,
DEPARTMENT ASC,
CASE WHEN LEVEL < 3
THEN LEVEL
ELSE (MOD((DENSE_RANK() OVER (PARTITION BY MANAGER ORDER BY EMPLOYEE_NUMBER ASC )) - 1,3) + 3) END ASC,
ADJUSTED_LEVEL ASC;
结果:
ADJUSTED_LEVEL EMPLOYEE_NUMBER MANAGER DEPARTMENT
1 10 1
2 200 10 2
3 2010 200 2
4 2040 200 2
5 2070 200 2
6 2100 200 2
3 2020 200 2
4 2050 200 2
5 2080 200 2
3 2030 200 2
4 2060 200 2
5 2090 200 2
2 300 10 3
3 3010 300 3
4 3040 300 3
5 3070 300 3
6 3100 300 3
3 3020 300 3
4 3050 300 3
5 3080 300 3
3 3030 300 3
4 3060 300 3
5 3090 300 3
2 400 10 4
3 4010 400 4
4 4040 400 4
5 4070 400 4
6 4100 400 4
3 4020 400 4
4 4050 400 4
5 4080 400 4
3 4030 400 4
4 4060 400 4
5 4090 400 4
2 500 10 5
3 5010 500 5
4 5040 500 5
5 5070 500 5
6 5100 500 5
3 5020 500 5
4 5050 500 5
5 5080 500 5
3 5030 500 5
4 5060 500 5
5 5090 500 5
下面是我的做法。
首先是测试数据(我包括了足够的员工来说明这一点,但不是每个中层经理有 10 名员工)。我遗漏了 phone 数字,因为它与手头的问题无关。
create table employee_table(employee_number, name, manager, department) as
select 1001, 'Big Boss', null, 100 from dual union all
select 1100, 'Beth Mgr', 1001, 100 from dual union all
select 1101, 'Jim' , 1100, 100 from dual union all
select 1102, 'Jackie' , 1100, 100 from dual union all
select 1103, 'Helen' , 1100, 100 from dual union all
select 1104, 'Tom' , 1100, 100 from dual union all
select 1105, 'Vance' , 1100, 100 from dual union all
select 1106, 'Rosa' , 1100, 100 from dual union all
select 1107, 'Chuck' , 1100, 100 from dual union all
select 1200, 'Duck Mgr', 1001, 200 from dual union all
select 1201, 'Danny' , 1200, 200 from dual union all
select 1202, 'Henry' , 1200, 200 from dual union all
select 1203, 'Mac' , 1200, 200 from dual union all
select 1204, 'Hassan' , 1200, 200 from dual union all
select 1205, 'Ann' , 1200, 200 from dual union all
select 1300, 'Adam Mgr', 1001, 300 from dual union all
select 1301, 'Wendy' , 1300, 300 from dual
;
然后查询。我希望输出遵循 "hierarchical order"(如果我们不必弄乱级别,就会这样)。为此,我首先 运行 层次查询,捕获 ROWNUM
以对最终结果进行排序,然后修改外部查询中的级别。请注意,我使用 LVL
作为列名; LEVEL
是保留字,因此不应用作列名。
select case lvl when 3 then lvl + ceil(rn/3) - 1 else lvl end as lvl,
employee_number, name, manager, department
from (
select level as lvl, employee_number, name, manager, department,
rownum as ord,
row_number() over
(partition by manager order by employee_number) as rn
from employee_table
start with manager is null
connect by prior employee_number = manager
)
order by ord
;
输出:
LVL EMPLOYEE_NUMBER NAME MANAGER DEPARTMENT
---------- --------------- -------- ---------- ----------
1 1001 Big Boss 100
2 1100 Beth Mgr 1001 100
3 1101 Jim 1100 100
3 1102 Jackie 1100 100
3 1103 Helen 1100 100
4 1104 Tom 1100 100
4 1105 Vance 1100 100
4 1106 Rosa 1100 100
5 1107 Chuck 1100 100
2 1200 Duck Mgr 1001 200
3 1201 Danny 1200 200
3 1202 Henry 1200 200
3 1203 Mac 1200 200
4 1204 Hassan 1200 200
4 1205 Ann 1200 200
2 1300 Adam Mgr 1001 300
3 1301 Wendy 1300 300
我正在使用 Oracle DBMS,我有一个关于分层查询的问题。
我正在使用分层 SQL 查询为我的部门创建一个组织列表。组织结构分为三个级别,依次是部门经理、部门经理和团队成员。
我目前的查询是:
SELECT level, employee_number, name, manager, department, phone
FROM employee_table
START WITH manager is null
CONNECT BY PRIOR employee_number = manager;
此查询生成一个分层列表,其中部门经理处于一级,每个部门经理处于二级,团队成员处于三级。总的来说,只有一个部门经理,三个科长,30个组员。
问题:我的要求是将列表中每个级别的员工数量限制为最多三名员工。前两级没问题,因为只有一个部门经理和三个科长(科长永远不会超过三个),但我现在三级有30个团队成员(每个科长管理10个团队成员) ).我的目标是在第 3 级有三个团队成员,在第 4 级有三个团队成员,在第 5 级有三个团队成员,等等。团队成员的顺序无关紧要,所以哪个团队成员在3 级,哪些团队成员处于 4 级,等等
我宁愿避免为了实现这个目标而将团队成员的经理设置为另一个团队成员的 employee_number。我可以在 employee_table 中创建另一个名为 "org_list_parent" 的列,并指出一个团队成员的 "org_list_parent" 是另一个团队成员的 employee_number,但我更愿意尽可能避免这样做。
有人对这个问题有什么想法吗?
提前谢谢你。
更新:
使用 mathguy 的查询,我能够获得最接近我想要达到的结果的输出。但是,如果可能的话,我想对输出进行一些调整。我正在使用此列表在 Oracle Apex 中构建组织结构图,并使用 mathguy 的 table 和查询,我得到以下输出:
这与我要制作的视觉效果非常接近。 “每个级别 3 个团队成员”背后的原因是试图防止图表在水平方向上过大。但是,如果你向左看,比如员工1104、1105、1106在1103下面,员工1107在1106下面。最好员工1104在1101下面,员工1105在1102下面,员工1106在1103下面,员工 1107 位于 1104 下方。是否有任何方法可以编辑查询以直观地生成该结果?
更新二:
alexgibbs 请求对他建议的两个不同查询的反馈作为我的问题的解决方案。以下是他的第一个查询:
SELECT CASE WHEN LEVEL < 3
THEN LEVEL
ELSE 3 + FLOOR((DENSE_RANK() OVER (PARTITION BY MANAGER ORDER BY
EMPLOYEE_NUMBER ASC ) - 1) / 3) END AS ADJUSTED_LEVEL,
EMPLOYEE_NUMBER, MANAGER
FROM EMPLOYEE_TABLE
START WITH MANAGER IS NULL
CONNECT BY PRIOR EMPLOYEE_NUMBER = MANAGER
ORDER BY 2 ASC, 1 ASC;
以下是此查询在 Oracle Apex 中作为列表的输出:
以下是他的第二个查询:
SELECT
CASE WHEN LEVEL < 3
THEN LEVEL
ELSE 3 + FLOOR((DENSE_RANK() OVER (PARTITION BY MANAGER ORDER BY
EMPLOYEE_NUMBER ASC ) - 1) / 3) END AS ADJUSTED_LEVEL,
EMPLOYEE_NUMBER,
MANAGER,
DEPARTMENT
FROM EMPLOYEE_TABLE
START WITH MANAGER IS NULL
CONNECT BY PRIOR EMPLOYEE_NUMBER = MANAGER
ORDER BY
NVL2(MANAGER,1,0) ASC,
DEPARTMENT ASC,
CASE WHEN LEVEL < 3
THEN LEVEL
ELSE (MOD((DENSE_RANK() OVER (PARTITION BY MANAGER ORDER BY EMPLOYEE_NUMBER
ASC )) - 1,3) + 3) END ASC,
ADJUSTED_LEVEL ASC;
下面是这个查询在 Oracle Apex 中的输出:
注意:已针对问题的更新进行了大量编辑,uncertain/not-tested 具有兼容性的顶点
下面的解决方案只会在第 2 级添加超过第三级的部门经理。但是对于第 3 级以上,如果在部门经理之外如何分配额外级别并不重要,可以仅根据 employee_id
。随着三人组中每个成员的伪下一级直接嵌套在下方的更新,这里是一个示例,根据员工 ID,在一个三人组中分配伪级别和子级别部门。
下面是一个示例数据集和查询。
CREATE TABLE EMPLOYEE_TABLE (
EMPLOYEE_NUMBER NUMBER,
MANAGER NUMBER DEFAULT NULL,
NAME CHARACTER VARYING(64 BYTE),
DEPARTMENT CHARACTER VARYING(64 BYTE),
PHONE CHARACTER VARYING(64 BYTE)
);
--Dept Manager
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (10,NULL, 1);
--Section Managers
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (200,10, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (300,10, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (400,10, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (500,10, 5);
-- Section Employees
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (2010,200, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (2020,200, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (2030,200, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (2040,200, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (2050,200, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (2060,200, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (2070,200, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (2080,200, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (2090,200, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (2100,200, 2);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (3010,300, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (3020,300, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (3030,300, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (3040,300, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (3050,300, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (3060,300, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (3070,300, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (3080,300, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (3090,300, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (3100,300, 3);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (4010,400, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (4020,400, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (4030,400, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (4040,400, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (4050,400, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (4060,400, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (4070,400, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (4080,400, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (4090,400, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (4100,400, 4);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (5010,500, 5);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (5020,500, 5);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (5030,500, 5);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (5040,500, 5);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (5050,500, 5);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (5060,500, 5);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (5070,500, 5);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (5080,500, 5);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (5090,500, 5);
INSERT INTO EMPLOYEE_TABLE(EMPLOYEE_NUMBER, MANAGER, DEPARTMENT) VALUES (5100,500, 5);
COMMIT;
已编辑 查询:
SELECT
CASE WHEN LEVEL < 3
THEN LEVEL
ELSE 3 + FLOOR((DENSE_RANK() OVER (PARTITION BY MANAGER ORDER BY EMPLOYEE_NUMBER ASC ) - 1) / 3) END AS ADJUSTED_LEVEL,
EMPLOYEE_NUMBER,
MANAGER,
DEPARTMENT
FROM EMPLOYEE_TABLE
START WITH MANAGER IS NULL
CONNECT BY PRIOR EMPLOYEE_NUMBER = MANAGER
ORDER BY
NVL2(MANAGER,1,0) ASC,
DEPARTMENT ASC,
CASE WHEN LEVEL < 3
THEN LEVEL
ELSE (MOD((DENSE_RANK() OVER (PARTITION BY MANAGER ORDER BY EMPLOYEE_NUMBER ASC )) - 1,3) + 3) END ASC,
ADJUSTED_LEVEL ASC;
结果:
ADJUSTED_LEVEL EMPLOYEE_NUMBER MANAGER DEPARTMENT
1 10 1
2 200 10 2
3 2010 200 2
4 2040 200 2
5 2070 200 2
6 2100 200 2
3 2020 200 2
4 2050 200 2
5 2080 200 2
3 2030 200 2
4 2060 200 2
5 2090 200 2
2 300 10 3
3 3010 300 3
4 3040 300 3
5 3070 300 3
6 3100 300 3
3 3020 300 3
4 3050 300 3
5 3080 300 3
3 3030 300 3
4 3060 300 3
5 3090 300 3
2 400 10 4
3 4010 400 4
4 4040 400 4
5 4070 400 4
6 4100 400 4
3 4020 400 4
4 4050 400 4
5 4080 400 4
3 4030 400 4
4 4060 400 4
5 4090 400 4
2 500 10 5
3 5010 500 5
4 5040 500 5
5 5070 500 5
6 5100 500 5
3 5020 500 5
4 5050 500 5
5 5080 500 5
3 5030 500 5
4 5060 500 5
5 5090 500 5
下面是我的做法。
首先是测试数据(我包括了足够的员工来说明这一点,但不是每个中层经理有 10 名员工)。我遗漏了 phone 数字,因为它与手头的问题无关。
create table employee_table(employee_number, name, manager, department) as
select 1001, 'Big Boss', null, 100 from dual union all
select 1100, 'Beth Mgr', 1001, 100 from dual union all
select 1101, 'Jim' , 1100, 100 from dual union all
select 1102, 'Jackie' , 1100, 100 from dual union all
select 1103, 'Helen' , 1100, 100 from dual union all
select 1104, 'Tom' , 1100, 100 from dual union all
select 1105, 'Vance' , 1100, 100 from dual union all
select 1106, 'Rosa' , 1100, 100 from dual union all
select 1107, 'Chuck' , 1100, 100 from dual union all
select 1200, 'Duck Mgr', 1001, 200 from dual union all
select 1201, 'Danny' , 1200, 200 from dual union all
select 1202, 'Henry' , 1200, 200 from dual union all
select 1203, 'Mac' , 1200, 200 from dual union all
select 1204, 'Hassan' , 1200, 200 from dual union all
select 1205, 'Ann' , 1200, 200 from dual union all
select 1300, 'Adam Mgr', 1001, 300 from dual union all
select 1301, 'Wendy' , 1300, 300 from dual
;
然后查询。我希望输出遵循 "hierarchical order"(如果我们不必弄乱级别,就会这样)。为此,我首先 运行 层次查询,捕获 ROWNUM
以对最终结果进行排序,然后修改外部查询中的级别。请注意,我使用 LVL
作为列名; LEVEL
是保留字,因此不应用作列名。
select case lvl when 3 then lvl + ceil(rn/3) - 1 else lvl end as lvl,
employee_number, name, manager, department
from (
select level as lvl, employee_number, name, manager, department,
rownum as ord,
row_number() over
(partition by manager order by employee_number) as rn
from employee_table
start with manager is null
connect by prior employee_number = manager
)
order by ord
;
输出:
LVL EMPLOYEE_NUMBER NAME MANAGER DEPARTMENT
---------- --------------- -------- ---------- ----------
1 1001 Big Boss 100
2 1100 Beth Mgr 1001 100
3 1101 Jim 1100 100
3 1102 Jackie 1100 100
3 1103 Helen 1100 100
4 1104 Tom 1100 100
4 1105 Vance 1100 100
4 1106 Rosa 1100 100
5 1107 Chuck 1100 100
2 1200 Duck Mgr 1001 200
3 1201 Danny 1200 200
3 1202 Henry 1200 200
3 1203 Mac 1200 200
4 1204 Hassan 1200 200
4 1205 Ann 1200 200
2 1300 Adam Mgr 1001 300
3 1301 Wendy 1300 300