用于从sql server中的查询获取以下输出的分层查询

Axs*_*Axs -3 sql-server

我有一张叫做emp的桌子.该表有以下数据.

empid  name Manager_id
1       A   Null
2       B   1
3       C   2
4       D   2
5       E   4
Run Code Online (Sandbox Code Playgroud)

我希望上表中的输出如下.

empid   name Manager_id Level1 Level2 Level3 Level4
1         A   null      A      null    null  null
2         B    1        A      B       null  null
3         C    2        A      B       C     null
4         D    2        A      B       D     D
5         E    4        A      B       D     E
Run Code Online (Sandbox Code Playgroud)

Mik*_*son 13

with C as
(
  select T.EmpID,
         T.ManagerID,
         T.Name,
         cast('' as xml).query('element X { attribute V {sql:column("T.Name")}}') as LvlXML
  from YourTable as T
  where T.ManagerID is null
  union all
  select T.EmpID,
         T.ManagerID,
         T.Name,
         C.LvlXML.query('., element X { attribute V {sql:column("T.Name")}}')
  from YourTable as T
    inner join C 
      on T.ManagerID = C.EmpID
)
select C.EmpID,
       C.Name,
       C.ManagerID,
       C.LvlXML.value('/X[1]/@V', 'varchar(100)') as Level1,
       C.LvlXML.value('/X[2]/@V', 'varchar(100)') as Level2,
       C.LvlXML.value('/X[3]/@V', 'varchar(100)') as Level3,
       C.LvlXML.value('/X[4]/@V', 'varchar(100)') as Level4,
       C.LvlXML.value('/X[5]/@V', 'varchar(100)') as Level5
from C;
Run Code Online (Sandbox Code Playgroud)

SQL小提琴

更新:

@ t-clausen.dk指出上面的查询的性能不是它可以是这样的,所以这里是一个更快的版本.

首先在ManagerIDwith 上添加索引Name作为包含列.

create index IX_YourTable_ManagerID on YourTable(ManagerID) include(Name)
Run Code Online (Sandbox Code Playgroud)

以及在递归时构建所需列的新查询.

with C as
(
  select T.EmpID,
         T.ManagerID,
         T.Name,
         T.Name as Level1,
         cast(null as varchar(100)) as Level2,
         cast(null as varchar(100)) as Level3,
         cast(null as varchar(100)) as Level4,
         1 as Lvl
  from YourTable as T
  where T.ManagerID is null
  union all
  select T.EmpID,
         T.ManagerID,
         T.Name,
         C.Level1,
         case when C.lvl = 1 then T.Name else C.Level2 end,
         case when C.lvl = 2 then T.Name else C.Level3 end,
         case when C.lvl = 3 then T.Name else C.Level4 end,
         C.Lvl + 1
  from YourTable as T
    inner join C 
      on T.ManagerID = C.EmpID
)
select C.EmpID,
       C.Name,
       C.ManagerID,
       C.Level1,
       C.Level2,
       C.Level3,
       C.Level4
from C;
Run Code Online (Sandbox Code Playgroud)

这给了你这个很好的小查询计划,在锚点和查询的递归部分都有索引搜索:

在此输入图像描述

SQL小提琴