Diese Antwort wurde komplett neu geschrieben. Das Original hat nicht unter allen Umständen funktioniert
Ich musste den CTE ändern, um die vollständige Einheitenhierarchie für jede Einheit als mögliche Wurzel (oberste Einheit) darzustellen. Es ermöglicht eine echte Hierarchie mit mehreren Kindern pro Unit.
Ich habe die Beispieldaten in diesem SQL Fiddle erweitert um einen Spieler beiden Einheiten 11 und 12 zuzuweisen. Es gibt korrekt die richtige Reihe für jeden von 3 Spielern zurück, die für eine Einheit auf einer Ebene unterhalb von Einheit 1 spielen.
Die „Root“-Unit-ID und die Liste der Spieler-IDs befinden sich praktischerweise in der äußersten WHERE-Klausel ganz unten, was es einfach macht, die IDs nach Bedarf zu ändern.
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 ist eine leicht optimierte Version, bei der die Einheiten-ID-Kriterien in den CTE eingebettet sind. Der CTE berechnet nur Hierarchien, die auf Einheiten basieren, bei denen die Eltern-ID die gewählte Einheiten-ID ist (in diesem Fall 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)
Hier ist meine ursprüngliche Antwort. Es funktioniert nur, wenn die Einheitenhierarchie darauf beschränkt ist, nur ein Kind pro Einheit zuzulassen. Das SQL-Fiddle-Beispiel in der Frage hat 3 untergeordnete Elemente für Einheit 1, sodass es fälschlicherweise mehrere Zeilen für die Spieler 3, 5 und 6 zurückgibt, wenn es gegen Einheit 1 ausgeführt wird
Hier ist ein SQL Fiddle das zeigt das 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)