2012-02-03 3 views
1

У меня есть обновление, которое должно быть выполнено. И я действительно застрял. Это классический иерархический вопрос таблицы сотрудников, но с завихрением. Пожалуйста, посмотрите на это дерево пользователей: employeesОбновление специального идентификатора в иерархической таблице сотрудников

(никакого отношения к моей проблеме, просто что-то я нашел с фотографиями Google)

Давайте предположим следующее идентификаторам:

RM1: EmpId 1, ParentId null 

AM1: EmpId 2, ParentId 1 

MGR1: EmpId 3, ParentId 2 

MGR2: EmpId 4, ParentId 2 

EMP1: EmpId 5, ParentId 3 

EMP2: EmpId 6, ParentId 3 

EMP3: EmpId 7, ParentId 4 

EMP4: EmpId 8, ParentId 4 

мне нужно добавьте еще один столбец, позвоните ему parentSpecialId. Этот идентификатор является идентификатором пользователя ниже root (AM1 и AM2). Все пользователи ниже AM1 и AM2 должны иметь parentSpecialId для пользователя ниже root.

Который дает нам:

RM1: EmpId 1, ParentId null parentSpecialId null 

AM1: EmpId 2, ParentId 1 parentSpecialId null 

MGR1: EmpId 3, ParentId 2 parentSpecialId 2 

MGR2: EmpId 4, ParentId 2 parentSpecialId 2 

EMP1: EmpId 5, ParentId 3 parentSpecialId 2 

EMP2: EmpId 6, ParentId 3 parentSpecialId 2 

EMP3: EmpId 7, ParentId 4 parentSpecialId 2 

EMP4: EmpId 8, ParentId 4 parentSpecialId 2 

Все, что я это CTE, который дает мне набор результатов с AM1 и AM2. Итак, мне нужно пройти весь путь до EMPX и обновить parentSpecialId с Id 2 для AM1 и то же самое для всех пользователей AM2. Конечно, это нужно динамическим, в реальной жизни у меня 12 таких пользователей ниже root.

Имеет ли смысл?

Вот мой КТР:

WITH EmpsCTE AS 
(
    SELECT id, parent, name, 0 AS EmployeeLevel 
    FROM Employee 
    WHERE parent = 0 
    UNION ALL 
    SELECT e.id, e.parent, e.name, EmployeeLevel + 1 
    FROM EmpsCTE AS p 
    JOIN Employee AS e ON e.parent = p.id 
) 
SELECT id, parent, name, EmployeeLevel 
From EmpsCTE where EmployeeLevel = 1 

О, и я использую SQL Server 2008 R2

+0

Для примера гораздо большей странности, демонстрируя, как создать полный путь от лорда Высокого палача (RM1) к крестьянину (EMP *), взгляните на [это] (http://stackoverflow.com/questions/ 8912992/how-to-correct-label-branch-of-a-tree-in-a-depth-first-search). – HABO

ответ

1

Образец данных:

declare @T table 
(
    Name varchar(10), 
    EmpId int, 
    ParentId int, 
    ParentSpecialID int 
); 

insert into @T(Name, EmpId, ParentId) values 
('RM1', 1, null), 
('AM1', 2, 1), 
('MGR1', 3, 2), 
('MGR2', 4, 2), 
('EMP1', 5, 3), 
('EMP2', 6, 3), 
('EMP3', 7, 4), 
('EMP4', 8, 4); 

Обновление заявление:

with C as 
(
    select T3.EmpId, 
     T2.EmpId as ParentSpecialId 
    from @T as T1 
    inner join @T as T2 
     on T1.EmpId = T2.ParentId 
    inner join @T as T3 
     on T2.EmpId = T3.ParentId 
    where T1.ParentId is null 
    union all 
    select T.EmpId, 
     C.ParentSpecialId 
    from @T as T 
    inner join C 
     on T.ParentId = C.EmpId  
) 
update T 
set ParentSpecialId = C.ParentSpecialId 
from @T as T 
    inner join C 
    on T.EmpId = C.EmpId 
1

Для обрабатывать дерево произвольной глубины:

declare @T table (Name varchar(16), EmpId int, ParentId int); 

insert into @T(Name, EmpId, ParentId) values 
    ('RM1', 1, null), 
    ('AM1', 2, 1), 
    ('MGR1', 3, 2), 
    ('MGR2', 4, 2), 
    ('EMP1', 5, 3), 
    ('EMP2', 6, 3), 
    ('EMP3', 7, 4), 
    ('EMP4', 8, 4), 
    ('AM2', 9, 1), 
    ('MGR3', 10, 9), 
    ('EMP5', 11, 10), 
    ('Brown Noser', 12, 11), 
    ('Intern', 13, 12), 
    ('Coop', 14, 13), 
    ('Nephew', 15, 14), 
    ('Contractor', 16, 15); 

; with CTE as (
    -- Start with the root(s). 
    select Name, EmpId, ParentId, 0 as Depth, Cast(NULL as Int) as parentSpecialId 
    from @T 
    where ParentId is NULL 
    union all 
    -- Add the direct reports one layer at a time. 
    select T.Name, T.EmpId, T.ParentId, CTE.Depth + 1, case when CTE.Depth = 1 then T.ParentId else CTE.parentSpecialId end 
    from CTE inner join 
     @T as T on T.ParentId = CTE.EmpID 
    where T.ParentId = CTE.EmpId 
) 
select *, 
    (select Name from CTE as R where R.EmpId = CTE.ParentId) as ReportsTo, 
    (select Name from CTE as SC where SC.EmpId = CTE.parentSpecialId) as SubCommander 
    from CTE 
    order by Depth, Name 

С благодарностью Mikael Eriksson за настройку данных образца!

+0

Привет извините за поздний ответ. Я взял user92546 cte и обновил способ, которым делает Mikael. Он уверен, что работает ... Спасибо, вы, ребята, рок – user1188463

Смежные вопросы