Показать сотрудников самого популярного менеджера? - PullRequest
0 голосов
/ 01 марта 2020

enter image description here

Как отобразить сотрудников самого популярного менеджера? Итак, у меня есть эта таблица, и мне нужно иметь имя и фамилию сотрудников самого популярного менеджера (здесь это будет менеджер с id = 124).

В запросе должно быть указано имя_имя и last_name и manager_id.

Как я могу это сделать?

Я полагаю, что он должен считать manager_id и порядок в des c, а затем ограничить 1, поэтому иметь только топ-менеджера и каким-то образом показать свою занятость

Ответы [ 4 ]

0 голосов
/ 02 марта 2020

Еще один способ сделать то же самое, что показал @ 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

Еще один способ сделать то же самое, но сделать его более интересным / вовлеченным, - это получить список сотрудников, принадлежащих к наиболее популярному менеджеру, а также другого менеджера. (выбран 3-й по популярности менеджер).

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             
0 голосов
/ 02 марта 2020

Как отобразить сотрудников самого популярного менеджера?

Если вы работаете с Oracle 12.1 или выше, вы можете использовать оконные функции для сортировки вместе с ограничивающим строку предложением:

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

Запрос на самостоятельное присоединение таблица для связи каждого сотрудника с его менеджером; затем мы сортируем набор результатов по убыванию количества сотрудников одного и того же менеджера и фильтруем верхнюю запись (записи), разрешая связи (при этом сохраняются только те сотрудники, которые относятся к менеджеру, у которого большинство сотрудников).


В более ранних версиях один из вариантов - агрегировать по менеджерам и ранжировать их по количеству сотрудников в подзапросе и использовать для фильтрации:

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
0 голосов
/ 02 марта 2020

Вы можете сделать это без каких-либо самостоятельных соединений, используя функции analyti c. Подсчитайте сотрудников с одним и тем же менеджером, затем сгенерируйте рейтинг по количеству сотрудников на менеджера от высшего к низшему, а затем отфильтруйте, чтобы показать только сотрудников с самым высоким рейтингом:

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

дБ <> скрипка здесь

0 голосов
/ 02 марта 2020
SELECT * FROM Employees ORDER BY MANAGER_ID DESC
...