Esta respuesta se ha reescrito por completo. El original no funcionó del todo en todas las circunstancias
Tuve que cambiar el CTE para representar la jerarquía de unidades completa para cada unidad como una posible raíz (unidad superior). Permite una verdadera jerarquía con múltiples hijos por Unidad.
Extendí los datos de muestra en este SQL Fiddle tener un jugador asignado a las unidades 11 y 12. Devuelve correctamente la fila correcta para cada uno de los 3 jugadores que juegan para una Unidad en algún nivel por debajo de la Unidad 1.
La identificación de la unidad "raíz" y la lista de identificaciones de jugadores se encuentran convenientemente en la cláusula WHERE más externa en la parte inferior, lo que facilita cambiar las identificaciones según sea necesario.
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)
Aquí hay una versión ligeramente optimizada que tiene los criterios de identificación de la unidad integrados en el CTE. El CTE solo calcula las jerarquías enraizadas en Unidades en las que la ID principal es la ID de unidad elegida (1 en este caso)
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)
Esta es mi respuesta original. Solo funciona si la jerarquía de la unidad está restringida para permitir solo un hijo por unidad. El ejemplo de SQL Fiddle en la pregunta tiene 3 hijos para la Unidad 1, por lo que devuelve falsamente varias filas para los jugadores 3, 5 y 6 si se ejecuta contra la Unidad 1
Aquí hay un SQL Fiddle que demuestra el problema.
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)