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;
SQL Fiddle
Update:
@t-clausen.dk pointed out that performence for the query above is not what it can be so here is a faster version.
First add an index on ManagerID
with Name
as an included column.
create index IX_YourTable_ManagerID on YourTable(ManagerID) include(Name)
And the new query that builds the needed columns as we go in the recursion.
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;
That gives you this nice little query plan with an index seek both in the anchor and in the recursive part of the query:

SQL Fiddle