По сути, у вас есть «дерево» сотрудников, и вы хотите рекурсивно пройти по нему. Вот для чего нужны рекурсивные CTE.
Мы определим «подчиненный» CTE, который расскажет нам обо всех «подчиненных отношениях» между всеми сотрудниками, включая «многоуровневое» подчинение. Если A является менеджером B, а B - менеджером C, тогда A имеет подчиненных B и C.
Во-первых, мы начнем со всех сотрудников, которые являются их собственными подчиненными. Это нерекурсивная часть.
SELECT id AS id1, id AS id2
FROM employee
Затем мы «расширяем на один уровень вниз» подчиненные отношения. если B подчиняется A, все сотрудники с B в качестве менеджера также подчиняются A. id1 остается как есть, id2 становится идентификатором «нижнего» сотрудника. Это рекурсивная часть.
SELECT s.id1, e.id
FROM subordinate s
JOIN employee e ON s.id2 = e.manager_id
Затем мы вставляем обе в рекурсивный CTE. Postgres будет повторять вторую часть столько раз, сколько необходимо, пока не будут добавлены новые строки. Таким образом, мы повторно обходим все дерево сотрудников.
WITH RECURSIVE subordinate AS (
SELECT id AS id1, id AS id2
FROM employee
UNION
SELECT s.id1, e.id
FROM subordinate s
JOIN employee e ON s.id2 = e.manager_id
)
select * from subordinate order by id1, id2;
Давайте проверим результат:
id1 | id2
-----+-----
1 | 1
1 | 11
1 | 12
1 | 13
1 | 19
11 | 11
11 | 13
12 | 12
12 | 19
13 | 13
19 | 19
Отлично! У меня все в подчинении. У 11 есть 11 и 13, а у самых младших сотрудников, таких как 13 и 19, есть только они сами.
Как только мы это сделаем, остальное легко.
Мы можем сделать еще один CTE, подсчитывая разрешенные заявки на сотрудника:
SELECT resolver_id as id, COUNT(*) as count
FROM tickets
GROUP BY resolver_id
, а затем мы вставляем все в окончательный запрос. Для каждого сотрудника просуммируйте разрешенное количество всех его подчиненных.
WITH RECURSIVE subordinate AS (
SELECT id AS id1, id AS id2
FROM employee
UNION
SELECT s.id1, e.id
FROM subordinate s
JOIN employee e ON s.id2 = e.manager_id
),
resolved as (
SELECT resolver_id as id, COUNT(*) as count
FROM tickets
GROUP BY resolver_id
)
SELECT s.id1, SUM(r.count)
FROM subordinate s
JOIN resolved r ON r.id = s.id2
GROUP BY s.id1;