0

我正在创建一个 SQL Server 2008 查询,该查询将输出公司中的员工列表以及他们所在的团队以及一个附加列。

组织树示例:

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

由于我试图使用 CASE 来检查级别是否为 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

非常感谢,伙计们!

4

2 回答 2

0

为什么你需要这个变量?我没有看到它随后被使用

于 2012-10-04T18:53:08.440 回答
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表格,为个人和团队分配名称。这不是必需的 - 它本身可能是最终查询。

另请注意,由于AllPeopleCTE 的构建方式是递归的,我们会在进行时计算级别 - 每次递归时,我们都会在Level该行所代表的值上加一。

于 2012-10-05T06:47:42.437 回答