Sql 将递归限制到特定级别-重复行
首先,这不是我的另一个同名问题的重复,我只是想不出一个更好的名字 我有一个名为Player的SQL表和另一个名为Unit的SQL表Sql 将递归限制到特定级别-重复行,sql,sql-server,sql-server-2008,recursion,Sql,Sql Server,Sql Server 2008,Recursion,首先,这不是我的另一个同名问题的重复,我只是想不出一个更好的名字 我有一个名为Player的SQL表和另一个名为Unit的SQL表 每个球员必须通过外键UnitID属于一个团队 通过递归字段ParentUnitID,每个单元可以属于另一个团队 ParentUnit可以是ParentUnit(无限递归),但玩家只能属于一个团队 一个单位可能有很多孩子 所以它可能是(自上而下) TeamA(最高级别) 团队B(属于^^^) TeamC(属于^^) 团队D(属于^^) 玩家1(属于^^) 我的
- 每个球员必须通过外键UnitID属于一个团队
- 通过递归字段ParentUnitID,每个单元可以属于另一个团队
- ParentUnit可以是ParentUnit(无限递归),但玩家只能属于一个团队
- 一个单位可能有很多孩子
- TeamA(最高级别)
- 团队B(属于^^^)
- TeamC(属于^^)
- 团队D(属于^^)
- 玩家1(属于^^)
- 我通过了PlayerID 1,2,3,4
- 我通过UnitID 2
Player3, TeamC
仅返回Player3,因为它是TeamB(ID 2)的唯一后代,而TeamC是返回的,因为它是Player3所属的最高级别单位(UnitID 2以下)
如果我通过了:
- 我通过了PlayerID 1,2,3,4
- 我通过UnitID 6
Player1, Team2
Player2, Team2
这个答案已被完全改写。原始版本并非在所有情况下都有效
我必须更改CTE,以将每个单元的完整单元层次结构表示为一个可能的根(顶部单元)。它允许一个真正的层次结构,每个单元有多个子级
我扩展了其中的示例数据,让玩家同时被分配到第11单元和第12单元。它正确地返回了3个玩家的正确行,这些玩家在1号单位下的某个级别上为一个单位比赛
“根”单元ID和玩家ID列表位于底部最外层的WHERE子句中,便于根据需要更改ID
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)
这是一个稍微优化的版本,在CTE中嵌入了机组ID标准。CTE仅计算以单元为根的层次结构,其中父ID是所选的单元ID(本例中为1)
这是我的原始答案。只有当单元层次结构被限制为每个单元只允许一个子单元时,它才起作用。问题中的SQL Fiddle示例在第1单元中有3个子元素,因此如果在第1单元中运行,它会错误地为玩家3、5和6返回多行 下面是一个例子来说明这个问题 这个答案已被完全改写。原始版本并非在所有情况下都有效 我必须更改CTE,以将每个单元的完整单元层次结构表示为一个可能的根(顶部单元)。它允许一个真正的层次结构,每个单元有多个子级 我扩展了其中的示例数据,让玩家同时被分配到第11单元和第12单元。它正确地返回了3个玩家的正确行,这些玩家在1号单位下的某个级别上为一个单位比赛 “根”单元ID和玩家ID列表位于底部最外层的WHERE子句中,便于根据需要更改ID
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)
这是一个稍微优化的版本,在CTE中嵌入了机组ID标准。CTE仅计算以单元为根的层次结构,其中父ID是所选的单元ID(本例中为1)
这是我的原始答案。只有当单元层次结构被限制为每个单元只允许一个子单元时,它才起作用。问题中的SQL Fiddle示例在第1单元中有3个子元素,因此如果在第1单元中运行,它会错误地为玩家3、5和6返回多行 下面是一个例子来说明这个问题
这就是你想要的:Vijay,把你想要的结果作为一个表格!你的问题毫无意义。你说“我想让每个玩家都在“TeamB”下,但是“Player4”的顶级单位应该是“TeamC”。为了做到这一点,我只想传入PlayerID和“TeamB”的ID。所以我说“让所有玩家和顶级单位在TeamB下,然后过滤掉除Player4之外的所有玩家。“对不起,这毫无意义,与SQLFiddle的数据和结果完全不符。@SteveKass-我在问题中添加了更多信息,说它是胡说八道似乎有点苛刻,但我能理解我在哪里失去了你!希望我的编辑更有意义,如果没有,请解释具体哪一部分(希望不是全部!)没有意义,我会尽力进一步解释。这就是你想要的:Vijay,以表格形式给出你想要的结果!你的问题毫无意义。你说“我想让每个球员都在“TeamB”下,但是“Player4”的顶级单位应该是“TeamC”。为了做到这一点,我只想传递“TeamB”的玩家ID和ID。所以我说“让所有球员和顶级单位在TeamB下”
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)
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)