Обновление SQL Server, вложенная иерархия - PullRequest
0 голосов
/ 03 октября 2019

Я пытаюсь решить проблему вложенной рекурсии. У меня есть пример таблицы: -

Employee    Manager     IsPartTime?
A           Null            0
B           A               1
C           B               1
D           C               0
E           B               0

Это простая таблица задач Employee-Manager с флагом IsPartTime. Поскольку работник с частичной занятостью не является постоянным, он не может быть менеджером любого постоянного сотрудника. Итак, мне нужно обновить D & E сотрудников до их соотв. исправить следующий уровень менеджера в иерархии. Итак, я стремлюсь достичь: -

Employee    Updated Manager    Old Manager
A               Null                -
B               A                   -
C               B                   -
D               A                   C
E               A                   B

Я пытался создать временную таблицу с помощью Recursive CTE, но проблема в том, что я получаю только 1 уровень, но мне нужно пройти вверх, пока какой-либо менеджер, которыйПостоянный найден.

;WITH EmployeeCTE AS
    (
        SELECT EmployeeId, ManagerId
        FROM Employee
        where Manager in ('C', 'B')

        UNION ALL

        select e.EmployeeId, e.ManagerId
        from Employee e
        inner join EmployeeCTE  cc 
            on e.Manager = cc.Employee
    )
    select * from EmployeeCTE

1 Ответ

0 голосов
/ 03 октября 2019

Предполагая, что я правильно интерпретирую данные, вот что у меня есть:

-- first, establish the hierarchy and while doing that
-- add a hierarchyid column
with d as (select * from (
    values
        (1, 'A', Null, 0),
        (2, 'B', 'A',  1),
        (3, 'C', 'B',  1),
        (4, 'D', 'C',  0),
        (5, 'E', 'B',  0)
    ) as x(ID, Employee, Manager, IsPartTime)
)
, r as (
    select ID, Employee, Manager, IsPartTime, cast(concat('/', d.ID, '/') as varchar(max)) as h
    from d
    where Manager is null

    union all

    select child.ID, child.Employee, child.Manager, child.IsPartTime, cast(concat(parent.h, child.ID, '/') as varchar(max)) as h
    from r as parent
    join d as child
        on child.Manager = parent.Employee
)
select ID, Employee, Manager, IsPartTime, cast(h as hierarchyid) as h
into #t
from r;

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

with u as (
    select *, (
        select top(1) Employee
        from #t as a
        -- this person is a subordinate of the person from the main table
        where t.h.IsDescendantOf(a.h) = 1 
            -- exclude the employee themselves from consideration
            and t.ID <> a.ID
            -- the manager needs to be full-time.
            and a.IsPartTime = 0
        order by a.h.GetLevel()
    ) as NewManager
    from #t as t
    where IsPartTime = 0
)
select *
from u
where Manager <> NewManager;
...