2012-02-03 10 views
1

更新が必要です。そして、私は本当に立ち往生しました。 これは古典的な階層的な従業員テーブルの質問ですが、ひねられています。 ユーザーのこの木を見てください: (私の問題とは全く関係のない、私はGoogleの画像で見つかっただけで何か)employees階層従業員テーブルの特別なIDを更新する

は以下同上のを想定します:

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と呼ぶことができます。 このIDは、ルート(AM1とAM2)以下のユーザーのIDです。 AM1およびAM2以下のすべてのユーザーは、rootSpecialIdを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 

私が持っているすべては私にAM1とAM2との結果セットを与えるこのCTEです。 だから私はEMPXまでずっと行き、 AM1の場合はId 2で、AM2の場合はすべてのユーザーが同じようにparentSpecialIdを更新する必要があります。もちろん、それは動的で、実生活では、私はこれらのユーザーのうち12人がルート以下にいる必要があります。

意味がありますか?

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

Lord High Executioner(RM1)からPeasant(EMP *)への完全な経路をどのように生成するかを実証する、もっと奇妙な例については、[this](http://stackoverflow.com/questions/)をご覧ください。 8912992/how-to-a-well-first-tree-in-a-depth-first-search)記事のポストを参照してください。 – HABO

答えて

1

サンプル・データを使用します:ここで

は私のCTEである

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

UPDATE文:

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を受け取り、Mikaelのやり方を更新しました。 それは確かに動作します....ありがとう、あなたたちはロック – user1188463

関連する問題