#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;