6

嗨说我有一张桌子:

Person:
PersonId
Name
ManagerId

所以 ManagerId 是对另一个人的引用。

所以数据库中可能有一个人:

1
Bob
null

2
Steve
1

3
Tim
2

所以 Bob 是 Steve 的经理,而 Steve 是 Tim 的经理。

所以我想做的是编写一个查询,让 Bob 管理下的所有人。无论是直接的还是间接的。所以我想同时得到史蒂夫和蒂姆。在同一行。

如果我写:

select * from Person
where ManagerId = 1 I would get only Steve.

我如何编写它,以便我直接或间接地让每个人都在 Bob 的领导下?

4

3 回答 3

6

您可以使用公用表表达式 (CTE) 来解决此问题。正如 Andrei 指出的那样,CTE 可用于递归(请参阅 Andrei 在他的帖子中包含的出色参考)。假设您有一个如下表:

create table Person
(
   PersonId int primary key,
   Name varchar(25),
   ManagerId int foreign Key references Person(PersonId)
)

让我们将以下数据插入到表中:

insert into Person (PersonId, Name, ManagerId) values 
    (1,'Bob', null),
    (2, 'Steve',1),
    (3, 'Tim', 2)
    (4, 'John', 3),
    (5, 'James', null),
    (6, 'Joe', 5)

那么我们想要一个查询,该查询将返回直接或间接向 Bob 报告的每个人,即 Steve、Tim 和 John。我们不想返回 James 和 Bob,因为他们没有向任何人报告,或者 Joe,因为他向 James 报告。这可以通过 CTE 查询来完成,如下所示:

WITH Managers AS 
( 
     --initialize
     SELECT PersonId, Name, ManagerId  
        FROM Person WHERE ManagerId =1
     UNION ALL 
     --recursion 
     SELECT p.PersonId, p.Name, p.ManagerId 
        FROM Person p INNER JOIN Managers m  
        ON p.ManagerId = m.PersonId 
) 
SELECT * FROM Managers

此查询返回正确的结果:

PersonId    Name                      ManagerId
----------- ------------------------- -----------
2           Steve                     1
3           Tim                       2
4           John                      3

编辑:假设 OP 使用 SQL Server 2005 或更高版本,此答案是有效的。我不知道这种语法在 MySQL 或 Oracle 中是否有效。

于 2012-05-27T23:52:32.037 回答
0

如果您使用的是 MS SQL Server 2005 或更高版本,则可以使用 CTE,正如@AndreiDrynov 指出的那样,如下所示:

;WITH Emps(PersonId, Name, PersonLevel, ManagerName)
AS
(
    SELECT PersonId, Name, 0 AS PersonLevel, 
           CONVERT(NVARCHAR(50), 'No Manager') AS ManagerName
    FROM Persons
    WHERE ManagerId IS NULL
    Union All
    SELECT p.PersonId, P.Name, e.PersonLevel + 1 , e.Name 
    FROM Persons p 
    INNER JOIN Emps e ON p.ManagerId = e.PersonId 
 ) 
SELECT * 
FROM Emps 
WHERE PersonLevel <= 2

此查询应为您提供以下信息:

  PersonId   |   Name  |  Peroson Level   |   Manager
 ------------+---------+------------------+--------------
     1           Bob           0             No Manager
     2          Steve          1                Bob
     3           Tim           2               Steve

你可以在这里看到它的实际效果:

演示

于 2012-05-27T23:48:44.127 回答
0
select * 
from Person A 
inner join Person B ON B.PersonID = A.ManagerID
where ManagerId = 1
于 2012-05-28T00:36:14.863 回答