Cela semble faire l'affaire. La clé est de réaliser que nous pouvons construire le chemin à l'envers et nous arrêter lorsque nous n'avons plus de parent à localiser :
DECLARE @t table (ID int not null, Name varchar(19) not null, ParentID int null)
insert into @t(ID,Name,ParentID) values
(1 ,'Alex',null),
(2 ,'John',null),
(3 ,'Don',1),
(4 ,'Philip',2),
(5 ,'Shiva',2),
(6 ,'San',3),
(7 ,'Antony',6),
(8 ,'Mathew',2),
(9 ,'Cyril',8),
(10,'Johan',9)
declare @search table (ID int not null)
insert into @search (ID) values (7),(10)
;With Paths as (
select s.ID as RootID,t.ID,t.ParentID,t.Name, CONVERT(varchar(max),t.Name) as Path
from
@search s
inner join
@t t
on
s.ID = t.ID
union all
select p.RootID,t.ID,t.ParentID,p.Name, t.Name + '->' + p.Path
from Paths p
inner join
@t t
on
p.ParentID = t.ID
)
select * from Paths where ParentID is null
Résultat :
RootID ID ParentID Name Path
----------- ----------- ----------- ------------------- ----------------------------
10 2 NULL Johan John->Mathew->Cyril->Johan
7 1 NULL Antony Alex->Don->San->Antony
(J'ai laissé des colonnes supplémentaires pour aider à montrer l'état final. Interroger le CTE sans filtrer peut également être instructif)
Je voudrais également avertir que je ne travaillerais généralement pas avec des chaînes délimitées si possible - ce n'est pas une bonne représentation lorsque SQL Server a des types conçus pour travailler avec plusieurs valeurs.