Câu trả lời này đã được viết lại hoàn toàn. Bản gốc không hoàn toàn hoạt động trong mọi trường hợp
Tôi đã phải thay đổi CTE để đại diện cho hệ thống phân cấp Đơn vị đầy đủ cho mọi Đơn vị như một gốc có thể có (đơn vị hàng đầu). Nó cho phép một hệ thống phân cấp thực sự với nhiều con trên mỗi Đơn vị.
Tôi đã mở rộng dữ liệu mẫu trong SQL Fiddle này để chỉ định một người chơi cho cả hai đơn vị 11 và 12. Nó trả về đúng hàng chính xác cho mỗi người trong số 3 người chơi chơi cho một Đơn vị ở một số cấp bên dưới Đơn vị 1.
ID đơn vị "gốc" và danh sách ID người chơi nằm trong mệnh đề WHERE ngoài cùng ở phía dưới một cách thuận tiện, giúp bạn dễ dàng thay đổi ID khi cần.
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)
Đây là phiên bản được tối ưu hóa một chút có tiêu chí ID đơn vị được nhúng trong CTE. CTE chỉ tính toán các cấu trúc phân cấp bắt nguồn từ các Đơn vị trong đó ID gốc là ID đơn vị đã chọn (1 trong trường hợp này)
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)
Đây là câu trả lời ban đầu của tôi. Nó chỉ hoạt động nếu Cấu trúc phân cấp đơn vị bị hạn chế để chỉ cho phép một phần tử con trên mỗi Đơn vị. Ví dụ SQL Fiddle trong câu hỏi có 3 hàng con cho Phần 1, vì vậy nó trả về sai nhiều hàng cho Người chơi 3, 5 và 6 nếu chạy với Phần 1
Đây là SQL Fiddle điều đó chứng tỏ vấn đề.
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)