Найти всех сотрудников, подотчетных руководителю, включая руководителей
У меня есть таблица как минимум с тремя столбцами: EMPLID, NAME, SUPERVISOR_ID. В одном запросе я хотел бы получить прямые отчеты от менеджеров, включая любые прямые отчеты от подчиненных менеджеров вплоть до самого низкого уровня персонала, когда ему предоставляется менеджер WHERE
пункт.
Я могу создать запрос, который покажет, кто сообщает кому:
SELECT MANAGER.[EMPLID] AS MANAGEREMPLID, MANAGER.[NAME], MANAGER.[SUPERVISOR_ID], STAFF.[EMPLID] AS STAFFEMPLID, STAFF.[NAME], STAFF.[SUPERVISOR_ID]
FROM MYHRTABLE AS MANAGER INNER JOIN MYHRTABLE AS STAFF
ON MANAGER.[EMPLID] = STAFF.[SUPERVISOR_ID]
ORDER BY MANAGER.[NAME], STAFF.[NAME]
или рекурсивный CTE, который, по-видимому, делает то же самое
WITH MYCTE
AS (
SELECT [EMPLID], [NAME],[SUPERVISOR_ID] FROM
(SELECT [EMPLID], [NAME],
CASE WHEN [EMPLID] = [SUPERVISOR_ID] THEN NULL ELSE [SUPERVISOR_ID] END AS [SUPERVISOR_ID]
FROM MYHRTABLE) AS MYDATA
WHERE [SUPERVISOR_ID] IS NULL
UNION ALL
SELECT MYDATA.[EMPLID], MYDATA.[NAME],MYDATA.[SUPERVISOR_ID] FROM
(SELECT [EMPLID], [NAME],
CASE WHEN [EMPLID] = [SUPERVISOR_ID] THEN NULL ELSE [SUPERVISOR_ID] END AS [SUPERVISOR_ID]
FROM MYHRTABLE) AS MYDATA INNER JOIN MYCTE ON MYDATA.[SUPERVISOR_ID] = MyCTE.[EMPLID]
WHERE MYDATA.[SUPERVISOR_ID] IS NOT NULL)
SELECT * FROM MyCTE
(утверждение случая, потому что у высшего менеджера есть поле наблюдателя, сообщающее себе)
То, что я искал, было способностью дать этому запросу четкое представление и проследить весь путь до персонала, который отчитывается перед этим менеджером. В моих двух примерах я чувствую, что вижу прямые отчеты, но каким-то образом мне нужно сделать еще одно объединение, чтобы увидеть остальную информацию.
И второй вопрос вроде связан с тем, что, исследуя это, кажется, что большинство людей решают найти менеджеров для прямых отчетов с использованием рекурсивного cte, когда я думаю, что это можно было бы решить с помощью первого присоединенного к нему запроса. Учитывая два запроса, которые я разместил, зачем мне использовать рекурсивный CTE для его решения, когда я мог бы использовать ту же таблицу, присоединенную к себе? Кажется, я получаю ту же информацию обратно?
Если это что-то значит, это будет работать на SQL Server 2012 или 2008.
1 ответ
Причина, по которой вы используете рекурсию, заключается в возможности детализации данных путем рекурсивного перехода на менеджер, используемый в качестве привязки, до тех пор, пока не останется больше ничего, чтобы найти и получить выходные данные в виде иерархии.
Запрос на соединение будет ограничен одним уровнем на соединение (попробуйте добавить where manager.emplid = 1
(или ж / д идентификатор менеджера) к нему и понаблюдайте за тем, что происходит). Если вы заранее знаете количество уровней, вы можете использовать левые соединения (по одному соединению на уровень).
Я бы изменил рекурсивное решение этого:
with src as (
select
[emplid]
, [name]
, case
when [emplid] = [supervisor_id] then null
else [supervisor_id]
end as [supervisor_id]
from myhrtable
), cte as (
select [emplid], [name], [supervisor_id], [emplid] as top_manager
from src
where [emplid] = 1 -- this is the manager you're interested in
-- it can be a sub-manager in the middle or the tree
union all -- or the top level manager rooting the tree
select src.[emplid], src.[name], src.[supervisor_id], top_manager
from src
inner join cte on src.[supervisor_id] = cte.[emplid]
where src.[emplid] <> top_manager
)
select * from cte