Ta odpowiedź została całkowicie przepisana. Oryginał nie działał we wszystkich okolicznościach
Musiałem zmienić CTE, aby reprezentować pełną hierarchię Jednostek dla każdej Jednostki jako możliwy korzeń (jednostka górna). Pozwala na prawdziwą hierarchię z wieloma dziećmi na jednostkę.
Rozszerzyłem przykładowe dane w tym SQL Fiddle mieć gracza przypisanego do obu jednostek 11 i 12. Prawidłowo zwraca prawidłowy rząd dla każdego z 3 graczy, którzy grają w Jednostkę na pewnym poziomie poniżej Jednostki 1.
Identyfikator jednostki „root” i lista identyfikatorów graczy są wygodnie umieszczone w zewnętrznej klauzuli WHERE na dole, co ułatwia zmianę identyfikatorów w razie potrzeby.
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)
Oto nieco zoptymalizowana wersja, która ma wbudowane kryteria identyfikatora jednostki w CTE. CTE oblicza tylko hierarchie zakorzenione w jednostkach, w których identyfikator nadrzędny jest wybranym identyfikatorem jednostki (w tym przypadku 1)
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)
Oto moja oryginalna odpowiedź. Działa tylko wtedy, gdy Hierarchia Jednostek jest ograniczona do zezwalania tylko na jedno dziecko na Jednostkę. Przykład SQL Fiddle w pytaniu ma 3 dzieci w jednostce 1, więc błędnie zwraca wiele wierszy dla graczy 3, 5 i 6, jeśli zostanie uruchomiony w jednostce 1
Oto SQL Fiddle to pokazuje problem.
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)