2012-10-04 47 views
0

我正在創建一個SQL Server 2008查詢,該查詢將輸出公司中的員工列表以及他們所在的團隊的附加列。該組織樹SQL - 在遞歸查詢中的SELECT中的CASE中的賦值

例子:

Level 0: CEO 
Level 1: A, B, and C 
Level 2: 
    For A:1,2,3 
    For B:4,5,6 
    For C:7,8,9 

在我的結果集,我應該看到三列 - 名(樹)的水平,和團隊。對於1,2和3,我會看到'A'作爲他們的團隊,2作爲關卡。 4,5和6,'B'和2等級。

我正在使用遞歸查詢來導航樹(沒有問題),但是因爲我需要將查詢中的隊名「攜帶」下來(如果存在級別8,它應該仍然顯示該人員在1水平,他們報告),我這樣做:

(...) 
UNION ALL 
-- Recursive Member Definition 
-- in here level increments one each time, and the team should output the child 
-- of the top manager 
SELECT A.treenodeid, A.parentnodeid, A.email, LEVEL+1, team = 
            CASE LEVEL 
             When 1 then SET @salead = A.Email 
             Else @salead 
            END 
    FROM XX as A 
    INNER JOIN TeamsTable as B on A.parentnodeid = b.treenodeID 

由於我試圖用一個案例來檢查級別爲1(更新隊名到任何團隊領導的電子郵件名稱是),SQL一直說,如果我有「SET附近不正確的語法」。

是否可以在CASE中進行這種分配?我環顧四周,並沒有發現如果這可以與我的遞歸案件。

這裏的所有查詢(假設根是 'JohnSmith對'):

WITH TeamsTable (treenodeid, parentnodeid, email, Level, team) 
AS 
( 
    -- Anchor - Level starts with 0, and the team is empty for the top manager 
    SELECT treenodeid,parentnodeid,email,0,''  
    FROM XX WHERE email = 'JohnSmith' 

    UNION ALL 

    -- Recursive Member Definition - in here level increments one each time, and the team should output the child of the top manager 
    SELECT 
     A.treenodeid, A.parentnodeid, A.email, LEVEL+1, team = 
           CASE LEVEL 
            When 1 then SET @salead = A.Email 
            Else @salead 
           END 
    FROM XX as A 
    INNER JOIN TeamsTable as B on A.parentnodeid = b.treenodeID 
) 

-- Statement that executes the CTE 
SELECT * 
FROM TeamsTable 

非常感謝你們!

回答

0

爲什麼你需要變量?我沒有看到它被隨後使用

+0

這應該作爲一個評論,不是答案 – Beth

+0

我用它在從TeamsTable選擇* - 它應該每行報告:人的電子郵件名稱,人的水平,誰是他們的領袖( salead)是。 – malvenko

0

我會從下往上處理這個問題,而不是從上到下。

你還沒有說過A,B,C或CEO應該在哪支球隊,所以我已經完成了。

我也包括在可用的形式的示例數據:

create table Org (
    ID int not null, 
    Name varchar(10) not null, 
    ParentID int null 
) 
go 
insert into Org (ID,Name,ParentID) values 
(1,'CEO',null), 
(2,'A',1), 
(3,'B',1), 
(4,'C',1), 
(5,'1',2), 
(6,'2',2), 
(7,'3',2), 
(8,'4',3), 
(9,'5',3), 
(10,'6',3), 
(11,'7',4), 
(12,'8',4), 
(13,'9',4) 

查詢:

;With AllPeople as (
    select ID,ID as LastParentID,ParentID as NextParentID, CASE WHEN ParentID is null THEN 0 ELSE 1 END as Level 
    from Org 
    union all 
    select ap.ID,ap.NextParentID,o.ParentID,Level + 1 
    from 
     AllPeople ap 
      inner join 
     Org o 
      on 
       ap.NextParentID = o.ID and 
       o.ParentID is not null 
), Roots as (
    select ID from Org where ParentID is null 
), RootedPeople as (
    select * from AllPeople where NextParentID is null or NextParentID in (select ID from Roots) 
), Names as (
    select 
     oself.Name, 
     oteam.Name as Team, 
     Level 
    from 
     RootedPeople rp 
      inner join 
     Org oself on rp.ID = oself.ID 
      left join 
     Org oteam on rp.LastParentID = oteam.ID 
) 
select * from Names 

結果:

Name  Team  Level 
---------- ---------- ----------- 
CEO  CEO  0 
A   A   1 
B   B   1 
C   C   1 
9   C   2 
8   C   2 
7   C   2 
6   B   2 
5   B   2 
4   B   2 
3   A   2 
2   A   2 
1   A   2 

說明的CTE的:

  • AllPeople是遞歸查詢,爬上組織樹直到到達根。我們使用兩列(LastParentIDNextParentID)來跟蹤層次的兩個層次 - 顯然,一旦我們到達根目錄,我們就需要在此之前的層次。
  • Roots找到所有沒有父母的人。這是我們如何識別AllPeople已完成的行,其中
  • RootedPeople其中我們發現從未成功找到任何父代的行或遞歸已達到樹頂端的行。
  • Names最後我們一起回Org表指定名稱的個人和團隊。這不是必要的 - 它可能是最終的查詢本身。

還要注意的是,由於遞歸的方式AllPeople CTE建成,我們計算出水平,我們去 - 我們每次遞歸的時候,我們添加一個到Level這行表示。