Tato odpověď byla kompletně přepsána. Originál se tak úplně nepovedl za všech okolností
Musel jsem změnit CTE, aby reprezentoval úplnou hierarchii jednotek pro každou jednotku jako možný kořen (horní jednotka). Umožňuje skutečnou hierarchii s více dětmi na jednotku.
Rozšířil jsem ukázková data v tomto SQL Fiddle mít hráče přiřazeného k oběma jednotkám 11 a 12. Správně vrátí správný řádek pro každého ze 3 hráčů, kteří hrají za jednotku na určité úrovni pod jednotkou 1.
ID "kořenové" jednotky a seznam ID hráčů je pohodlně v nejvzdálenější klauzuli WHERE ve spodní části, což usnadňuje změnu ID podle potřeby.
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)
Zde je mírně optimalizovaná verze, která má kritéria Unit ID vložená do CTE. CTE počítá pouze hierarchie založené na jednotkách, kde rodičovské ID je zvolené ID jednotky (v tomto případě 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)
Zde je moje původní odpověď. Funguje pouze v případě, že je hierarchie jednotek omezena tak, aby povolovala pouze jednoho potomka na jednotku. Příklad SQL Fiddle v otázce má 3 potomky pro Unit 1, takže falešně vrací více řádků pro hráče 3, 5 a 6, pokud běží proti Unit 1
Zde je SQL Fiddle to demonstruje problém.
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)