递归 SQL 自连接
Recursive SQL self join
我有以下员工 table 并且 EmpID
和 ManagerID
之间存在外键关系。
员工Table
期望输出
我希望能够以 >
分隔的层次顺序显示员工姓名,从最顶层的经理到最底层,EmpID 是层次结构底部的员工 ID。
我知道我可以通过使用以下 SQL.
将 table 连接到自身来获得所需的输出
select e1.empID, e1.DeptID, e2.Name + ' > ' + e1.Name as Description
from employee e1
left join employee e2
on e1.managerId = e2.empId
我也知道我可以在上面的查询中添加更多的左连接以获得所需的输出。但是层次结构的深度没有限制,所以我想它需要动态完成。
如有任何帮助,我们将不胜感激
您想要递归 CTE:
with e as (
select cast(name as varchar(max)) as list, empId, 0 as level
from employees
where managerID is null
union all
select e.list + '>' + e2.name, e2.empId, level + 1
from e join
employees e2
on e.empId = e2.managerId
)
select e.*
from e
where not exists (select 1
from employees e2
where e2.managerId = e.empId
);
declare @Employees table (
EmpId int ,
DeptId int ,
Name varchar(30) ,
ManagerId int
);
insert into @Employees values
( 1, 1, 'Zippy' , 2 ),
( 2, 1, 'George' , 3 ),
( 3, 1, 'Bungle' , 4 ),
( 4, 1, 'Geoffrey' , null ),
( 5, 2, 'Rod' , 6 ),
( 6, 2, 'Jane' , 7 ),
( 7, 2, 'Freddy' , null );
with cte as
(
select
EmpId ,
DeptId ,
ManagerId ,
Path = cast('' as varchar(4000)),
Name ,
Level = 0
from
@Employees
where
ManagerId is null
union all
select
EmpId = e.EmpId,
DeptId = e.DeptId,
ParentId = e.ManagerId,
Path = cast(concat(cte.Path, cte.Name, ' › ') as varchar(4000)),
Name = e.Name,
Level = cte.Level + 1
from
@Employees e
inner join cte on cte.EmpId = e.ManagerId
)
select
EmpId ,
DeptId ,
ManagerId ,
Path ,
Name ,
FullPath = Path + Name,
Level
from
cte
order by
FullPath;
我有以下员工 table 并且 EmpID
和 ManagerID
之间存在外键关系。
员工Table
期望输出
我希望能够以 >
分隔的层次顺序显示员工姓名,从最顶层的经理到最底层,EmpID 是层次结构底部的员工 ID。
我知道我可以通过使用以下 SQL.
将 table 连接到自身来获得所需的输出select e1.empID, e1.DeptID, e2.Name + ' > ' + e1.Name as Description
from employee e1
left join employee e2
on e1.managerId = e2.empId
我也知道我可以在上面的查询中添加更多的左连接以获得所需的输出。但是层次结构的深度没有限制,所以我想它需要动态完成。
如有任何帮助,我们将不胜感激
您想要递归 CTE:
with e as (
select cast(name as varchar(max)) as list, empId, 0 as level
from employees
where managerID is null
union all
select e.list + '>' + e2.name, e2.empId, level + 1
from e join
employees e2
on e.empId = e2.managerId
)
select e.*
from e
where not exists (select 1
from employees e2
where e2.managerId = e.empId
);
declare @Employees table (
EmpId int ,
DeptId int ,
Name varchar(30) ,
ManagerId int
);
insert into @Employees values
( 1, 1, 'Zippy' , 2 ),
( 2, 1, 'George' , 3 ),
( 3, 1, 'Bungle' , 4 ),
( 4, 1, 'Geoffrey' , null ),
( 5, 2, 'Rod' , 6 ),
( 6, 2, 'Jane' , 7 ),
( 7, 2, 'Freddy' , null );
with cte as
(
select
EmpId ,
DeptId ,
ManagerId ,
Path = cast('' as varchar(4000)),
Name ,
Level = 0
from
@Employees
where
ManagerId is null
union all
select
EmpId = e.EmpId,
DeptId = e.DeptId,
ParentId = e.ManagerId,
Path = cast(concat(cte.Path, cte.Name, ' › ') as varchar(4000)),
Name = e.Name,
Level = cte.Level + 1
from
@Employees e
inner join cte on cte.EmpId = e.ManagerId
)
select
EmpId ,
DeptId ,
ManagerId ,
Path ,
Name ,
FullPath = Path + Name,
Level
from
cte
order by
FullPath;