Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Giới hạn đệ quy ở mức nhất định - Các hàng trùng lặp

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)


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm cách nào để nối nhiều hàng có cùng id trong sql?

  2. Làm cách nào để trích xuất chuỗi con cụ thể này trong SQL Server?

  3. SQL Pivot với nhiều cột

  4. Chuỗi kết nối cho localdb cho phiên bản 11 là gì

  5. SQL Server 2008:Lỗi chuyển đổi kiểu dữ liệu nvarchar thành float