PostgreSQL - рекурсивное самоподсоединение CTE для иерархии менеджеров - PullRequest
0 голосов
/ 02 февраля 2019

У меня проблемы с составлением рекурсивного запроса в PostgreSQL, чтобы показать иерархию управления между сотрудниками.Чтобы достичь этого, мне нужно было бы самостоятельно присоединить таблицу к себе, пока каждый сотрудник не достигнет конца своей иерархии.Мои данные выглядят так в данный день:

+------------+-------------+-----------------+---------------------+
|    date    | employee_id | terminated_flag | manager_employee_id |
+------------+-------------+-----------------+---------------------+
| 2019-01-31 |           3 |               0 |                   2 |
| 2019-01-31 |           2 |               1 |                   1 |
| 2019-01-31 |           1 |               0 |                     |
+------------+-------------+-----------------+---------------------+

В идеале я хотел бы создать столбец JSONB, содержащий полную иерархию и детали менеджера для данного сотрудника.Я знаю, что могу добавить к существующему столбцу JSONB с помощью рекурсии, но борьба с этим была проблемой.Желаемый результат будет выглядеть следующим образом (удаляя столбцы для удобства чтения):

+------------+-------------+-----------------------------------------------------------+
|    date    | employee_id |                     manager_hierarchy                     |
+------------+-------------+-----------------------------------------------------------+
| 2019-01-31 |           3 | {{"level":1,"id":2,"term":1},{"level":2,"id":1,"term":0}} |
| 2019-01-31 |           2 | {{"level":1,"id":1,"term":0}}                             |
| 2019-01-31 |           1 |                                                           |
+------------+-------------+-----------------------------------------------------------+

В моем наборе данных может быть N уровней от любого сотрудника до руководителя, поэтому рекурсию нужно будет завершитькак только каждый сотрудник достиг генерального директора, у которого будет значение NULL для manager_employee_id.

Возможно ли это?Спасибо за вашу помощь!

1 Ответ

0 голосов
/ 02 февраля 2019

Я бы рассматривал это как рекурсивный CTE для получения иерархии, а затем для агрегирования для создания значения jsonb:

with recursive t as (
      select v.*
      from (values (3, 2, 0), (2, 1, 1), (1, null, 0)) v(employee_id, manager_employee_id, terminated_flag)
     ),
     cte as (
      select distinct employee_id, manager_employee_id, terminated_flag, 1 as lev
      from t
      union all
      select cte.employee_id, t.manager_employee_id, t.terminated_flag, lev + 1
      from cte join
           t
           on cte.manager_employee_id = t.employee_id
     )
select employee_id, jsonb_agg(jsonb_build_object('level', lev, 'id', manager_employee_id, 'terminated_flag', terminated_flag))
from cte
group by employee_id;

Здесь - это db <> скрипка.

...