вложенный запрос, чтобы получить количество сотрудников под менеджерами - PullRequest
1 голос
/ 11 ноября 2019
create table employee (
Id int,
ManagerId int);

insert into employee values
(1, 3),
(2, 3),
(3, 6),
(4, 7),
(5, 7),
(6, 8),
(7, 6);

select * from employee;

вот таблица:

enter image description here

, как написать запрос, чтобы получить менеджеров с числом сотрудников под ними. Обратите внимание на вложенную структуру. результат для приведенного выше примера будет

Id | number_of_employees
3  | 2
7  | 2
6  | 6
8  | 7

1 Ответ

2 голосов
/ 12 ноября 2019

Вот, пожалуйста !!

With recursive cte as (
     select id,Managerid from employee  --> Anchor Query
     union all
     select c.Id,e.ManagerId from cte c --> Recursive Member
     join employee e on (c.ManagerId=e.Id)) --> Termination Condition
select ManagerId,count(Id) as Number_of_Employees
from cte group by ManagerId

Демо

Обновление

Хорошо, позвольте мне попытаться объяснить.

Сначала нам нужно сгенерировать таблицу, в которой перечислены работники под руководством менеджера и менеджера этого менеджера до верхнего уровня ( все комбинации ). Это должно быть что-то вроде ниже справа? Давайте назовем это Результирующая таблица

-------------------------
|   Id  |   ManagerId   |
-------------------------
|   1   |       3       |--
|   2   |       3       |  |
|   3   |       6       |  |
|   4   |       7       |  |->From your table
|   5   |       7       |  |
|   6   |       8       |  |
|   7   |       6       |-- 
|   2   |       6       |--
|   1   |       6       |  |
|   7   |       8       |  |
|   3   |       8       |  |
|   5   |       6       |  |-> Nested structure which you meant in the question
|   4   |       6       |  |
|   4   |       8       |  |
|   5   |       8       |  |
|   1   |       8       |  |
|   2   |       8       |--
-------------------------

Как только мы получим приведенную выше таблицу, будет простым запросом получить count с использованием group by ManagerID. Итак, как мы этого добьемся.

1) Мы можем привлечь непосредственных сотрудников, используя

select Id,ManagerId from employee -- let's call this as QueryE1

2) Теперь давайте объединимся за одной таблицей, чтобы получить менеджеров первого уровня со своими сотрудниками.

select e1.Id,e2.ManagerId from employee e1 join employee e2 on e1.managerid = e2.id     
--QueryE2
-------------------------
|   Id  |   ManagerId   |
-------------------------
|   1   |       6       |
|   2   |       6       |
|   3   |       8       |
|   7   |       8       |
|   4   |       6       |
|   5   |       6       |
-------------------------

3) Затем мы должны рассмотреть приведенную выше таблицу как Справочную таблицу (QueryE2) и выяснить менеджеров второго уровня со своими сотрудниками, соединившись с таблицей сотрудников. Здесь, поскольку 8 - менеджер 6, все репортеры из 6 - также репортеры 8.

SELECT e3.id,e4.managerid 
FROM   (SELECT e1.id,e2.managerid 
        FROM employee e1 JOIN employee e2 
                 ON e1.managerid = e2.id) e3 
JOIN employee e4 
ON e3.managerid = e4.id -- QueryE3

-------------------------
|   Id  |   ManagerId   |
-------------------------
|   1   |       8       |
|   2   |       8       |
|   4   |       8       |
|   5   |       8       |
-------------------------

4) Мы должны повторять вышеупомянутые шаги, пока не останется больше Менеджеров для Менеджеров. Теперь мы знаем, что нет менеджера для 8. Но давайте посмотрим, что говорит запрос. Теперь мы должны рассмотреть самую последнюю таблицу (выше) как справочную таблицу.

SELECT e5.id,e6.managerid 
FROM   (SELECT e3.id,e4.managerid 
        FROM   (SELECT e1.id,e2.managerid 
                FROM   employee e1 
                       JOIN employee e2 
                         ON e1.managerid = e2.id) e3 
        JOIN employee e4 
        ON e3.managerid = e4.id) e5 
JOIN employee e6 
ON e5.managerid = e6.id  --QueryE4-- returns 0 rows as well

Наконец, если мы объединим ( union ) все значения из всех этих запросов, мы получим требуемые Таблица результатов . Все это делается нашим RECURSIVE CTE в одном запросе. Здесь QueryE1 является Якорным Запросом. QueryE2,QueryE3 & QueryE4 являются рекурсивными членами, и они создаются нашим CTE, пока мы не получим 0 строк. После создания Resultant Table мы можем использовать его для настройки наших потребностей. Здесь мы делаем Group by, чтобы получить count ManagerID. Я не уверен, удалит ли это ваше замешательство, но, по крайней мере, надеюсь, что вы поймете:)

...