Sql 将递归限制到某个级别
我有一个名为Player的SQL表和另一个名为Team的SQL表Sql 将递归限制到某个级别,sql,sql-server,sql-server-2008,recursion,Sql,Sql Server,Sql Server 2008,Recursion,我有一个名为Player的SQL表和另一个名为Team的SQL表 每个玩家必须通过外键TeamID属于一个团队 通过递归字段ParentTeamID,每个团队可以属于另一个团队 所以它可能是(自上而下) TeamA 团队B 76队 第8组 我的球员 我的问题是,如果给我一个球员的PlayerID(该表的PK),那么获得顶级球队的最佳方式是什么 到目前为止我的查询(得到所有团队): 现在,虽然我认为这是一个正确的开始,但我认为可能有更好的方法。而且我有点被卡住了!我尝试在连接中使用Leve
- 每个玩家必须通过外键
属于一个团队TeamID
- 通过递归字段
,每个团队可以属于另一个团队ParentTeamID
- TeamA
- 团队B
- 76队
- 第8组
- 我的球员
PlayerID
(该表的PK),那么获得顶级球队的最佳方式是什么
到目前为止我的查询(得到所有团队):
现在,虽然我认为这是一个正确的开始,但我认为可能有更好的方法。而且我有点被卡住了!我尝试在连接中使用Level(在子查询中),但没有成功
有没有关于如何在树上工作,只获取顶层细节的想法
编辑:
父团队可以是父团队(无限递归),但玩家只能属于一个团队
数据结构
小组:
TeamID(主键)、名称、ParentTeamID(递归字段)
玩家:
玩家ID(主键)、姓名、团队ID(FK)
样本数据:
Team:
1, TeamA, NULL
2, TeamB, 1
3, Team76, 2
4, Group8, 3
Player:
1, Player_ME, 4
2, Player_TWO, 2
因此,有了上述数据,两个玩家都应该(在查询中)显示他们有一个TeamA的“TopLevelTeam”
否则你会得到一个巨大的重复行,类似于玩家数量的平方,不是吗
--
(以下评论后)
完全正确,我误读了模式。听着,你不需要把球员带到最后。我认为球队树的安排可能因球员而异,但事实并非如此。所以
WITH recursive TeamTree AS (
SELECT TeamID, ParentTeamID FROM Team T1
UNION ALL
SELECT T1.TeamID, T2.ParentTeamID FROM T1 JOIN T2 ON T1.ParentTeamID=T2.TeamID
)
SELECT TeamTree.* FROM TeamTree JOIN Team T3
ON TeamTree.ParentTeamID=T3.TeamID WHERE T3.ParentTeamID IS NULL;
这将为您提供每个团队及其根祖先的表。现在将其加入玩家表
SELECT * FROM Player JOIN (WITH TeamTree AS (
SELECT TeamID, ParentTeamID FROM Team T1
UNION ALL
SELECT T1.TeamID, T2.ParentTeamID FROM T1 JOIN T2 ON T1.ParentTeamID=T2.TeamID
)
SELECT TeamTree.* FROM TeamTree JOIN Team T3
ON TeamTree.ParentTeamID=T3.TeamID WHERE T3.ParentTeamID IS NULL) teamtree2
ON Player.TeamID=teamtree2.TeamID;
如果需要更多列,您可以重新加入团队
否则你会得到一个巨大的重复行,类似于玩家数量的平方,不是吗
--
(以下评论后)
完全正确,我误读了模式。听着,你不需要把球员带到最后。我认为球队树的安排可能因球员而异,但事实并非如此。所以
WITH recursive TeamTree AS (
SELECT TeamID, ParentTeamID FROM Team T1
UNION ALL
SELECT T1.TeamID, T2.ParentTeamID FROM T1 JOIN T2 ON T1.ParentTeamID=T2.TeamID
)
SELECT TeamTree.* FROM TeamTree JOIN Team T3
ON TeamTree.ParentTeamID=T3.TeamID WHERE T3.ParentTeamID IS NULL;
这将为您提供每个团队及其根祖先的表。现在将其加入玩家表
SELECT * FROM Player JOIN (WITH TeamTree AS (
SELECT TeamID, ParentTeamID FROM Team T1
UNION ALL
SELECT T1.TeamID, T2.ParentTeamID FROM T1 JOIN T2 ON T1.ParentTeamID=T2.TeamID
)
SELECT TeamTree.* FROM TeamTree JOIN Team T3
ON TeamTree.ParentTeamID=T3.TeamID WHERE T3.ParentTeamID IS NULL) teamtree2
ON Player.TeamID=teamtree2.TeamID;
如果您需要更多专栏,您可以重新加入
团队。我相信这就是您想要的,免费提供一些额外信息:-)
安德鲁在他编辑的版本中有正确的想法,但我认为他的实现是不正确的
架构和查询可在
编辑-回答评论中的问题
只需第二次加入CTE,您就可以导航到玩家团队层级中的任何级别。在你的情况下,你要求的是排名第二的团队:
我相信这就是你要找的,免费提供一些额外的信息:-)
安德鲁在他编辑的版本中有正确的想法,但我认为他的实现是不正确的
架构和查询可在
编辑-回答评论中的问题
只需第二次加入CTE,您就可以导航到玩家团队层级中的任何级别。在你的情况下,你要求的是排名第二的团队:
顶级团队是什么意思?你能展示几行样本数据并展示你想要的结果吗?那么你是说你目前的方法有效吗?团队的深度如何?家长可以有家长吗?@AaronBertrand我已经修改了我的问题,加入了结构和样本数据。@AbeMiessler不,我当前的方法显示了一名球员所属的所有球队,但我只想要最顶端的一支(带有“NULL”ParentTeamID的球队)。top team
是什么意思?你能展示几行样本数据并展示你想要的结果吗?那么你是说你目前的方法有效吗?团队的深度如何?家长可以有家长吗?@AaronBertrand我已经修改了我的问题,加入了结构和样本数据。@AbeMiessler不,我当前的方法显示了一名球员所属的所有球队,但我只想要最顶端的一支(带有“NULL”ParentTeamID的球队)和UrPlayerID=ChildTeam.PlayerID/*ADDED*/“部分是错误的,因为没有相等项,但即使有了这条线(或者根本没有这条线),我还是得到了更低的单位。因此,在您的示例中(使用我的数据),查看玩家“player_ME”会返回“Group8”,这是最低的团队(就在玩家的正上方)。。。我需要它返回“TeamA”。不幸的是,我得到的多部分标识符T1无法绑定到这一行“SELECT T1.TeamID,T2.ParentTeamID FROM T1 JOIN T2 on T1.ParentTeamID=T2.TeamID”我已经试着填空,但我想不出来……请尝试从TeamTree T1 JOIN T2中选择。不幸的是,我没有从办公室很好地访问数据库,而且我很难记住递归查询的语法。谢谢你的帮助,但是dbbenham有一个稍微不同的解决方案,我将使用它。再次感谢你!:)“AND UrPlayerID=ChildTeam.PlayerID/*ADDED*/”部分是一个错误,因为没有相等项,但即使有这条线(或者根本没有这条线),我也得到了较低的单位。因此,在您的示例中(使用我的数据),查看玩家“player_ME”会返回“Group8”,这是最低的团队(就在玩家的正上方)。。。我需要它返回“TeamA”。不幸的是,我得到的多部分标识符T1无法绑定到这一行“SELECT T1.TeamID,T2.ParentTeamID FROM T1 JOIN T2 on T1.ParentTeamID=T2.TeamID”我已经试着填空,但我想不出来……请尝试从TeamTree T1 JOIN T2中选择。不幸的是,我没有从办公室很好地访问数据库,而且我很难记住递归查询的语法。谢谢你的帮助,但是dbbenham有一个稍微不同的解决方案,我将使用它。再次感谢你!:)啊,你从最高层开始工作,然后一直工作到球员的团队。真是妙不可言!起初我还以为是巫毒呢!:)还有一个简单的问题——如果我想获得排名第二的顶级单位,我会怎么做?(仍然是问题标题的一部分)
with teamCTE as (
select TeamID,
TeamName,
cast(null as int) as ParentTeamID,
cast(null as varchar(10)) as ParentTeamName,
TeamID TopTeamID,
TeamName TopTeamName,
1 as TeamLevel
from team
where ParentTeamID is null
union all
select t.TeamID,
t.TeamName,
c.TeamID,
c.TeamName,
c.TopTeamID,
c.TopTeamName,
TeamLevel+1 as TeamLevel
from team t
join teamCTE c
on t.ParentTeamID = c.TeamID
)
select p.PlayerID,
p.PlayerName,
t.*
from player p
join teamCTE t
on p.TeamID = t.TeamID
with teamCTE as (
select TeamID,
TeamName,
cast(null as int) as ParentTeamID,
cast(null as varchar(10)) as ParentTeamName,
TeamID TopTeamID,
TeamName TopTeamName,
1 as TeamLevel
from team
where ParentTeamID is null
union all
select t.TeamID,
t.TeamName,
c.TeamID,
c.TeamName,
c.TopTeamID,
c.TopTeamName,
TeamLevel+1 as TeamLevel
from team t
join teamCTE c
on t.ParentTeamID = c.TeamID
)
select p.PlayerID,
p.PlayerName,
t1.*,
t2.TeamID Level2TeamID,
t2.TeamName Level2TeamName
from player p
join teamCTE t1
on p.TeamID = t1.TeamID
join teamCTE t2
on t1.TopTeamID = t2.TopTeamID
and t2.TeamLevel=2