Обновите специальный идентификатор в иерархической таблице сотрудников - PullRequest
1 голос
/ 04 февраля 2012

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

(совершенно не связано с моей проблемой, просто что-то, что я нашел с картинками 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.

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

Вот мой CTE:

    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

Ответы [ 2 ]

1 голос
/ 04 февраля 2012

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

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

Спасибо Микаэлю Эрикссону за настройку данных выборки!

1 голос
/ 04 февраля 2012

Пример данных:

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
...