Sql-запрос для получения иерархии организационного уровня из одной таблицы

#sql

#sql

Вопрос:

У меня есть одна таблица с именем employee. Пожалуйста, обратитесь к приведенной ниже таблице, и мне нужен уровень, на котором сотрудник отчитывается перед каким менеджером. Я не знаю, какова будет логика. Я использовал CTE, но не получаю ожидаемого результата.Пожалуйста, помогите мне в этом случае для получения ожидаемого результата.

Сотрудник таблицы

 EmpID.                     EmpName.                         ManagerID
1                             A                                Null
2                             B                                  1
3                             C                                  1
4                             D                                  2
5                             E                                  3
6                             F                                  4
7                             G                                  5
8                             H                                  5
 

Ожидаемый результат

 EmpName.                      ManagerName                         Level
A                                Null                                1
B                                  A                                 2
C                                  A                                 2
D                                  B                                 3
E                                  C                                 4
F                                  D                                 5
G                                  E                                 6
H                                  E                                 6
 

Комментарии:

1. Какой продукт СУБД вы используете? «SQL» — это просто язык запросов, а не название конкретного продукта базы данных. Пожалуйста , добавьте тег для продукта базы данных , который вы используете postgresql , oracle , db2 , sql-server , …

2. Вам не нужен cte. Присоедините таблицу к самой себе через manager I’d, вторая таблица будет содержать имя менеджера.

Ответ №1:

Предполагая, что вы используете Sql Server , вы можете сделать это с помощью следующего кода:

 WITH cte (EmpId, EmpName, ManagerName, LEVEL) AS (
SELECT EmpId, EmpName, CAST('' AS VARCHAR) as ManagerName, 1 AS LEVEL
FROM Employee
WHERE ManagerId IS NULL

UNION ALL

SELECT e1.EmpId, e1.EmpName, CAST(cte.EmpName AS VARCHAR) ManagerName, (cte.LEVEL   1) AS LEVEL
FROM Employee e1
    JOIN cte ON e1.ManagerId = cte.EmpId    
)

SELECT EmpName, ManagerName, LEVEL FROM cte
ORDER BY EmpName
 

Обратите внимание, что вам необходимо пересмотреть уровни в вашем ожидаемом выходе. Например, для сотрудника H иерархия H => E => C => A , которая показывает, что это уровень 4 . Правильные уровни следующие:

 EmpName  ManagerName  Level    
A                     1
B        A            2
C        A            2
D        B            3
E        C            3
F        D            4
G        E            4
H        E            4
 

Комментарии:

1. Спасибо rad за ваше драгоценное время и четкое решение, и да, этот запрос работает нормально..

Ответ №2:

Рекурсивный CTE работает в Postgresql.

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

 WITH RECURSIVE RCTE AS
( 
    SELECT 
     EmpID AS BaseEmpID, 
     ManagerID AS BaseManagerID,
     1 AS Lvl, 
     EmpID, 
     ManagerID
    FROM employee

    UNION ALL

    SELECT 
     c.BaseEmpID,
     c.BaseManagerID,
     Lvl   1,
     m.EmpID,
     m.ManagerID
    FROM RCTE c
    JOIN employee m 
      ON m.EmpID = c.ManagerID
)
, EMPLEVELS AS
(
    SELECT 
     BaseEmpID, 
     BaseManagerID, 
     MAX(Lvl) AS Level
    FROM RCTE
    GROUP BY BaseEmpID, BaseManagerID
)
SELECT 
 e.EmpName, 
 m.EmpName AS ManagerName,
 elvl.Level
FROM EMPLEVELS elvl
JOIN employee e ON e.EmpID = elvl.BaseEmpID
LEFT JOIN employee m ON m.EmpID = elvl.BaseManagerID
ORDER BY elvl.BaseEmpID;
 

ВОЗВРАТ:

 empname managername level
A       NULL        1
B       A           2
C       A           2
D       B           3
E       C           3
F       D           4
G       E           4
H       E           4
 

Тот же запрос работает в MS Sql Server, если РЕКУРСИВНОЕ слово удалено.

Ответ №3:

Я думаю, вам нужен простой join :

 select e.name, em.name as manager_name
from employees e left join
     employees em
     on e.managerId = em.empId;