当表有自己的链接时的SQL查询

Ano*_*use 6 sql t-sql recursion common-table-expression

嗨说我有一张桌子:

Person:
PersonId
Name
ManagerId
Run Code Online (Sandbox Code Playgroud)

所以ManagerId是一个回复给另一个人的参考.

所以数据库中可能有人:

1
Bob
null

2
Steve
1

3
Tim
2
Run Code Online (Sandbox Code Playgroud)

所以鲍勃是史蒂夫的经理而史蒂夫是蒂姆的经理.

所以我想要做的就是编写一个查询,让Bob管理下的所有人.直接或间接.所以我想要得到史蒂夫和蒂姆.在同一条线上.

如果我写:

select * from Person
where ManagerId = 1 I would get only Steve.
Run Code Online (Sandbox Code Playgroud)

我怎么写它所以我直接或间接地让每个人都在Bob下?

Joe*_*ano 6

您可以使用公用表表达式(CTE)来解决此问题.正如安德烈指出的那样,CTE可以用于递归(参见Andrei在其帖子中包含的优秀参考文献).假设你有一张表如下:

create table Person
(
   PersonId int primary key,
   Name varchar(25),
   ManagerId int foreign Key references Person(PersonId)
)
Run Code Online (Sandbox Code Playgroud)

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

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)
Run Code Online (Sandbox Code Playgroud)

然后我们想要一个查询,它将返回所有直接或间接向Bob报告的人,这些人将是Steve,Tim和John.我们不想归还詹姆斯和鲍勃,因为他们向詹姆斯报告,因为他们向任何人或乔报告.这可以通过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
Run Code Online (Sandbox Code Playgroud)

此查询返回正确的结果:

PersonId    Name                      ManagerId
----------- ------------------------- -----------
2           Steve                     1
3           Tim                       2
4           John                      3
Run Code Online (Sandbox Code Playgroud)

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