Dit antwoord is volledig herschreven. Het origineel werkte niet helemaal onder alle omstandigheden
Ik moest de CTE wijzigen om de volledige eenheidshiërarchie voor elke eenheid weer te geven als een mogelijke root (topeenheid). Het maakt een echte hiërarchie mogelijk met meerdere kinderen per eenheid.
Ik heb de voorbeeldgegevens uitgebreid in deze SQL Fiddle om een speler toegewezen te krijgen aan beide eenheden 11 en 12. Het geeft de juiste rij terug voor elk van de 3 spelers die voor een eenheid spelen op een bepaald niveau onder eenheid 1.
De "root" Unit-ID en de lijst met speler-ID's staan handig in de buitenste WHERE-clausule onderaan, waardoor het gemakkelijk is om de ID's indien nodig te wijzigen.
with UnitCTE as (
select u.UnitID,
u.Designation UnitDesignation,
u.ParentUnitID as ParentUnitID,
p.Designation as ParentUnitDesignation,
u.UnitID TopUnitID,
u.Designation TopUnitDesignation,
1 as TeamLevel
from Unit u
left outer join Unit p
on u.ParentUnitId = p.UnitID
union all
select t.UnitID,
t.Designation UnitDesignation,
c.UnitID as ParentUnitID,
c.UnitDesignation as ParentUnitDesignation,
c.TopUnitID,
c.TopUnitDesignation,
TeamLevel+1 as TeamLevel
from Unit t
join UnitCTE c
on t.ParentUnitID = c.UnitID
)
select p.PlayerID,
p.Designation,
t1.*
from UnitCTE t1
join UnitCTE t2
on t2.TopUnitID = t1.UnitID
and t2.TopUnitID = t1.TopUnitID
join Player p
on p.UnitID = t2.UnitID
where t1.ParentUnitID = 1
and playerID in (1,2,3,4,5,6)
Hier is een enigszins geoptimaliseerde versie waarin de Unit ID-criteria zijn ingebed in de CTE. De CTE berekent alleen hiërarchieën die zijn geworteld in Units waarbij Parent ID de gekozen Unit ID is (1 in dit geval)
with UnitCTE as (
select u.UnitID,
u.Designation UnitDesignation,
u.ParentUnitID as ParentUnitID,
p.Designation as ParentUnitDesignation,
u.UnitID TopUnitID,
u.Designation TopUnitDesignation,
1 as TeamLevel
from Unit u
left outer join Unit p
on u.ParentUnitId = p.UnitID
where u.ParentUnitID = 1
union all
select t.UnitID,
t.Designation UnitDesignation,
c.UnitID as ParentUnitID,
c.UnitDesignation as ParentUnitDesignation,
c.TopUnitID,
c.TopUnitDesignation,
TeamLevel+1 as TeamLevel
from Unit t
join UnitCTE c
on t.ParentUnitID = c.UnitID
)
select p.PlayerID,
p.Designation,
t1.*
from UnitCTE t1
join UnitCTE t2
on t2.TopUnitID = t1.UnitID
join Player p
on p.UnitID = t2.UnitID
where playerID in (1,2,3,4,5,6)
Hier is mijn oorspronkelijke antwoord. Het werkt alleen als de eenheidshiërarchie beperkt is tot het toestaan van slechts één kind per eenheid. Het SQL Fiddle-voorbeeld in de vraag heeft 3 onderliggende items voor Unit 1, dus het retourneert ten onrechte meerdere rijen voor Spelers 3, 5 en 6 als deze wordt uitgevoerd tegen Unit 1
Hier is een SQL Fiddle dat toont het probleem aan.
with UnitCTE as
select UnitID,
Designation UnitDesignation,
ParentUnitID as ParentUnitID,
cast(null as varchar(50)) as ParentUnitDesignation,
UnitID TopUnitID,
Designation TopUnitDesignation,
1 as TeamLevel
from Unit
where ParentUnitID is null
union all
select t.UnitID,
t.Designation UnitDesignation,
c.UnitID,
c.UnitDesignation,
c.TopUnitID,
c.TopUnitDesignation,
TeamLevel+1 as TeamLevel
from Unit t
join UnitCTE c
on t.ParentUnitID = c.UnitID
)
select p.PlayerID,
p.Designation,
t2.*
from Player p
join UnitCTE t1
on p.UnitID = t1.UnitID
join UnitCTE t2
on t2.TopUnitID = t1.TopUnitID
and t1.TeamLevel >= t2.TeamLevel
join UnitCTE t3
on t3.TopUnitID = t1.TopUnitID
and t2.TeamLevel = t3.TeamLevel+1
where t3.UnitID = 2
and playerID in (1,2,3,4)