显示员工最受欢迎的经理?
Display the employees of the most popular manager?
如何显示最受欢迎经理的员工?
所以,我得到了这个 table,我需要知道最受欢迎的经理的员工的名字和姓氏(这里是 id = 124 的经理)。
查询应显示 first_name 和 last_name 和 manager_id。
我该怎么做?
我想它应该计数 manager_id 并按 desc 排序,然后限制 1,因此只有最高经理并以某种方式显示他的雇员
SELECT * FROM Employees ORDER BY MANAGER_ID DESC
How can I display the employees of the most popular manager?
如果您是 运行 Oracle 12.1 或更高版本,您可以使用 window 函数进行排序,以及行限制子句:
select
e.*,
m.first_name manager_first_name,
m.last_name manager_last_name
from employees e
inner join employees m on m.employee_id = e.manager_id
order by count(*) over(partition by e.manager_id) desc
fetch next 1 rows with ties
查询自连接 table 以将每个员工与其经理相关联;然后我们按同一经理的员工人数降序对结果集进行排序,并过滤顶部记录,允许联系(这只保留与拥有最多员工的经理相关的员工)。
在早期版本中,一种选择是按经理聚合并按子查询中的员工数量对他们进行排名,然后将其用于过滤:
select
e.*,
m.first_name manager_first_name,
m.last_name manager_last_name
from employees e
inner join employees m on m.employee_id = e.manager_id
inner join (
select manager_id, rank() over(order by count(*) desc) rn
from employees
group by manager_id, first_name, last_name
) x on x.rn = 1 and x.manager_id = e.manager_id
您可以通过使用分析函数在没有任何自连接的情况下完成。计算拥有同一经理的员工数,然后根据每个经理的员工数从高到低生成排名,然后过滤以仅显示排名靠前的员工:
SELECT *
FROM (
SELECT e.*,
RANK() OVER ( ORDER BY num_emps_with_same_manager DESC ) AS rnk
FROM (
SELECT e.*,
COUNT(*) OVER ( PARTITION BY manager_id ) AS num_emps_with_same_manager
FROM employees e
) e
)
WHERE rnk = 1
因此,为您测试数据(删除了不必要的列):
CREATE TABLE employees ( employee_id, manager_id ) AS
SELECT 100, NULL FROM DUAL UNION ALL
SELECT 101, 100 FROM DUAL UNION ALL
SELECT 102, 100 FROM DUAL UNION ALL
SELECT 200, 101 FROM DUAL UNION ALL
SELECT 205, 101 FROM DUAL UNION ALL
SELECT 206, 205 FROM DUAL UNION ALL
SELECT 149, 100 FROM DUAL UNION ALL
SELECT 174, 149 FROM DUAL UNION ALL
SELECT 176, 149 FROM DUAL UNION ALL
SELECT 178, 149 FROM DUAL UNION ALL
SELECT 124, 100 FROM DUAL UNION ALL
SELECT 141, 124 FROM DUAL;
查询输出直属员工数最多的经理的所有员工详情:
EMPLOYEE_ID | MANAGER_ID | NUM_EMPS_WITH_SAME_MANAGER | RNK
----------: | ---------: | -------------------------: | --:
149 | 100 | 4 | 1
101 | 100 | 4 | 1
102 | 100 | 4 | 1
124 | 100 | 4 | 1
db<>fiddle here
@MT0 在他的回答中展示的另一种方法。我的更多评论是稍微修改一下,但我无法评论(缺少声誉点数)所以添加为新答案(抱歉)。
with q1 as (
select
employee_id, manager_id,
COUNT(1) OVER ( PARTITION BY manager_id ) AS num_emps_with_same_manager
from employees e
),
q2 as (
select
employee_id, manager_id,
num_emps_with_same_manager,
RANK() OVER ( ORDER BY num_emps_with_same_manager DESC ) AS rnk,
min(manager_id) keep (DENSE_RANK FIRST ORDER BY num_emps_with_same_manager DESC, manager_id ASC) over () as most_pop_mgr_asc_id
from q1
)
select *
from q2
where 1=1
--and rnk = 1
and manager_id = most_pop_mgr_asc_id
order by 1
;
也提供最受欢迎的经理。
EMPLOYEE_ID MANAGER_ID NUM_EMPS_WITH_SAME_MANAGER RNK MOST_POP_MGR_ASC_ID
101 100 4 1 100
102 100 4 1 100
124 100 4 1 100
149 100 4 1 100
另一种方法可以达到相同的效果,但会增加 interesting/involved 是获取属于最受欢迎的经理以及另一位经理(选择第三大最受欢迎的经理)的员工列表。
with q1 as (
select
employee_id, manager_id, COUNT(1) OVER ( PARTITION BY manager_id ) AS num_emps_with_same_manager
from employees e
),
q2 as (
select
employee_id, manager_id, num_emps_with_same_manager,
DENSE_RANK() OVER ( ORDER BY num_emps_with_same_manager DESC ) AS rnk,
min(manager_id) keep (DENSE_RANK FIRST ORDER BY num_emps_with_same_manager DESC, manager_id ASC) over () as most_pop_mgr_asc_id,
min(num_emps_with_same_manager) keep (DENSE_RANK FIRST ORDER BY num_emps_with_same_manager DESC, manager_id ASC) over () as most_pop_mgr_num_emps,
listagg(employee_id, ',') WITHIN GROUP (ORDER by employee_id ASC) OVER (PARTITION BY manager_id) as mgr_emps
from q1
),
q3 as (
select
q2.num_emps_with_same_manager as mgr_#emps, q2.manager_id as mgr, q2.rnk, q2.most_pop_mgr_asc_id as pop1_mgr, q2.most_pop_mgr_num_emps as pop1_mgr_#emps,
cast(NTH_VALUE(min(mgr_emps), 1) OVER (ORDER BY num_emps_with_same_manager DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as varchar2(20)) as pop1_mgr_emps,
cast(min(case when rnk = 1 then mgr_emps end) over () as varchar2(20)) as pop1_mgr_emps_alt,
cast(NTH_VALUE(min(manager_id), 3) OVER (ORDER BY num_emps_with_same_manager DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as integer) as pop3_mgr,
cast(NTH_VALUE(min(num_emps_with_same_manager), 3) OVER (ORDER BY num_emps_with_same_manager DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as integer) as pop3_mgr_#emps,
cast(NTH_VALUE(min(mgr_emps), 3) OVER (ORDER BY num_emps_with_same_manager DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as varchar2(20)) as pop3_mgr_emps,
cast(min(case when rnk = 3 then mgr_emps end) over () as varchar2(20)) as pop3_mgr_emps_alt
from q2
where 1=1
--and rnk = 1
--and manager_id = most_pop_mgr_asc_id
group by manager_id, num_emps_with_same_manager, rnk, most_pop_mgr_asc_id, most_pop_mgr_num_emps, case when rnk = 1 then mgr_emps end, case when rnk = 3 then mgr_emps end
order by 1 desc
)
select *
from q3
where rnk = 1
;
给予
MGR_#EMPS MGR RNK POP1_MGR POP1_MGR_#EMPS POP1_MGR_EMPS POP1_MGR_EMPS_ALT POP3_MGR POP3_MGR_#EMPS POP3_MGR_EMPS POP3_MGR_EMPS_ALT
---------- ---------- ---------- ---------- -------------- -------------------- -------------------- ---------- -------------- -------------------- --------------------
4 100 1 100 4 101,102,124,149 101,102,124,149 101 2 200,205 200,205
如何显示最受欢迎经理的员工? 所以,我得到了这个 table,我需要知道最受欢迎的经理的员工的名字和姓氏(这里是 id = 124 的经理)。
查询应显示 first_name 和 last_name 和 manager_id。
我该怎么做?
我想它应该计数 manager_id 并按 desc 排序,然后限制 1,因此只有最高经理并以某种方式显示他的雇员
SELECT * FROM Employees ORDER BY MANAGER_ID DESC
How can I display the employees of the most popular manager?
如果您是 运行 Oracle 12.1 或更高版本,您可以使用 window 函数进行排序,以及行限制子句:
select
e.*,
m.first_name manager_first_name,
m.last_name manager_last_name
from employees e
inner join employees m on m.employee_id = e.manager_id
order by count(*) over(partition by e.manager_id) desc
fetch next 1 rows with ties
查询自连接 table 以将每个员工与其经理相关联;然后我们按同一经理的员工人数降序对结果集进行排序,并过滤顶部记录,允许联系(这只保留与拥有最多员工的经理相关的员工)。
在早期版本中,一种选择是按经理聚合并按子查询中的员工数量对他们进行排名,然后将其用于过滤:
select
e.*,
m.first_name manager_first_name,
m.last_name manager_last_name
from employees e
inner join employees m on m.employee_id = e.manager_id
inner join (
select manager_id, rank() over(order by count(*) desc) rn
from employees
group by manager_id, first_name, last_name
) x on x.rn = 1 and x.manager_id = e.manager_id
您可以通过使用分析函数在没有任何自连接的情况下完成。计算拥有同一经理的员工数,然后根据每个经理的员工数从高到低生成排名,然后过滤以仅显示排名靠前的员工:
SELECT *
FROM (
SELECT e.*,
RANK() OVER ( ORDER BY num_emps_with_same_manager DESC ) AS rnk
FROM (
SELECT e.*,
COUNT(*) OVER ( PARTITION BY manager_id ) AS num_emps_with_same_manager
FROM employees e
) e
)
WHERE rnk = 1
因此,为您测试数据(删除了不必要的列):
CREATE TABLE employees ( employee_id, manager_id ) AS
SELECT 100, NULL FROM DUAL UNION ALL
SELECT 101, 100 FROM DUAL UNION ALL
SELECT 102, 100 FROM DUAL UNION ALL
SELECT 200, 101 FROM DUAL UNION ALL
SELECT 205, 101 FROM DUAL UNION ALL
SELECT 206, 205 FROM DUAL UNION ALL
SELECT 149, 100 FROM DUAL UNION ALL
SELECT 174, 149 FROM DUAL UNION ALL
SELECT 176, 149 FROM DUAL UNION ALL
SELECT 178, 149 FROM DUAL UNION ALL
SELECT 124, 100 FROM DUAL UNION ALL
SELECT 141, 124 FROM DUAL;
查询输出直属员工数最多的经理的所有员工详情:
EMPLOYEE_ID | MANAGER_ID | NUM_EMPS_WITH_SAME_MANAGER | RNK ----------: | ---------: | -------------------------: | --: 149 | 100 | 4 | 1 101 | 100 | 4 | 1 102 | 100 | 4 | 1 124 | 100 | 4 | 1
db<>fiddle here
@MT0 在他的回答中展示的另一种方法。我的更多评论是稍微修改一下,但我无法评论(缺少声誉点数)所以添加为新答案(抱歉)。
with q1 as (
select
employee_id, manager_id,
COUNT(1) OVER ( PARTITION BY manager_id ) AS num_emps_with_same_manager
from employees e
),
q2 as (
select
employee_id, manager_id,
num_emps_with_same_manager,
RANK() OVER ( ORDER BY num_emps_with_same_manager DESC ) AS rnk,
min(manager_id) keep (DENSE_RANK FIRST ORDER BY num_emps_with_same_manager DESC, manager_id ASC) over () as most_pop_mgr_asc_id
from q1
)
select *
from q2
where 1=1
--and rnk = 1
and manager_id = most_pop_mgr_asc_id
order by 1
;
也提供最受欢迎的经理。
EMPLOYEE_ID MANAGER_ID NUM_EMPS_WITH_SAME_MANAGER RNK MOST_POP_MGR_ASC_ID
101 100 4 1 100
102 100 4 1 100
124 100 4 1 100
149 100 4 1 100
另一种方法可以达到相同的效果,但会增加 interesting/involved 是获取属于最受欢迎的经理以及另一位经理(选择第三大最受欢迎的经理)的员工列表。
with q1 as (
select
employee_id, manager_id, COUNT(1) OVER ( PARTITION BY manager_id ) AS num_emps_with_same_manager
from employees e
),
q2 as (
select
employee_id, manager_id, num_emps_with_same_manager,
DENSE_RANK() OVER ( ORDER BY num_emps_with_same_manager DESC ) AS rnk,
min(manager_id) keep (DENSE_RANK FIRST ORDER BY num_emps_with_same_manager DESC, manager_id ASC) over () as most_pop_mgr_asc_id,
min(num_emps_with_same_manager) keep (DENSE_RANK FIRST ORDER BY num_emps_with_same_manager DESC, manager_id ASC) over () as most_pop_mgr_num_emps,
listagg(employee_id, ',') WITHIN GROUP (ORDER by employee_id ASC) OVER (PARTITION BY manager_id) as mgr_emps
from q1
),
q3 as (
select
q2.num_emps_with_same_manager as mgr_#emps, q2.manager_id as mgr, q2.rnk, q2.most_pop_mgr_asc_id as pop1_mgr, q2.most_pop_mgr_num_emps as pop1_mgr_#emps,
cast(NTH_VALUE(min(mgr_emps), 1) OVER (ORDER BY num_emps_with_same_manager DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as varchar2(20)) as pop1_mgr_emps,
cast(min(case when rnk = 1 then mgr_emps end) over () as varchar2(20)) as pop1_mgr_emps_alt,
cast(NTH_VALUE(min(manager_id), 3) OVER (ORDER BY num_emps_with_same_manager DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as integer) as pop3_mgr,
cast(NTH_VALUE(min(num_emps_with_same_manager), 3) OVER (ORDER BY num_emps_with_same_manager DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as integer) as pop3_mgr_#emps,
cast(NTH_VALUE(min(mgr_emps), 3) OVER (ORDER BY num_emps_with_same_manager DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as varchar2(20)) as pop3_mgr_emps,
cast(min(case when rnk = 3 then mgr_emps end) over () as varchar2(20)) as pop3_mgr_emps_alt
from q2
where 1=1
--and rnk = 1
--and manager_id = most_pop_mgr_asc_id
group by manager_id, num_emps_with_same_manager, rnk, most_pop_mgr_asc_id, most_pop_mgr_num_emps, case when rnk = 1 then mgr_emps end, case when rnk = 3 then mgr_emps end
order by 1 desc
)
select *
from q3
where rnk = 1
;
给予
MGR_#EMPS MGR RNK POP1_MGR POP1_MGR_#EMPS POP1_MGR_EMPS POP1_MGR_EMPS_ALT POP3_MGR POP3_MGR_#EMPS POP3_MGR_EMPS POP3_MGR_EMPS_ALT
---------- ---------- ---------- ---------- -------------- -------------------- -------------------- ---------- -------------- -------------------- --------------------
4 100 1 100 4 101,102,124,149 101,102,124,149 101 2 200,205 200,205