我有一个名为Player的SQL表,另一个名为Team。
TeamID
属于一个团队。ParentTeamID
属于另一个团队。所以它可能是(自上而下)......
我的问题是,如果我给了玩家PlayerID
(该表的PK),那么获得顶级团队的最佳方法是什么?
到目前为止我的查询(获得所有团队):
WITH TeamTree
AS (
SELECT ParentTeam.*, Player.PlayerID, 0 as Level
FROM Team ParentTeam
INNER JOIN Player ON Player.TeamID = ParentTeam.TeamID
WHERE Player.PlayerID IN (SELECT * FROM dbo.Split(@PlayerIDs,','))
UNION ALL
SELECT ChildTeam.*, TeamTree.PlayerID AS PlayerID, TeamTree.Level + 1
FROM Team ChildTeam
INNER JOIN TeamTree TeamTree
ON ChildTeam.TeamID = TeamTree.ParentTeamID
)
现在虽然我认为这是一个合适的起点,但我认为可能有更好的方法。另外,我有点卡住了!我尝试在连接中使用Level(在子查询中),但它没有工作。
关于如何在树上工作并获得最高级别详细信息的任何想法?
编辑:
ParentTeam可以是ParentTeam(无限递归),但玩家只能属于一个团队。
数据结构 球队: TeamID(PK),Name,ParentTeamID(递归字段)
播放器: PlayerID(PK),名称,TeamID(FK)
示例数据:
Team:
1, TeamA, NULL
2, TeamB, 1
3, Team76, 2
4, Group8, 3
Player:
1, Player_ME, 4
2, Player_TWO, 2
因此,根据上述数据,两位玩家都应该(在查询中)显示他们有一个" TopLevelTeam" TeamA
答案 0 :(得分:3)
我相信这就是你要找的东西,免费提供一些额外的信息:-) 安德鲁在他的编辑版本中有正确的想法,但我认为他的实施是不正确的。
架构和查询位于SQL Fiddle
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
编辑 - 回答评论中的问题
只需第二次加入CTE,即可导航到玩家团队层次结构中的任何级别。在您的情况下,您要求排名第二的团队:SQL Fiddle
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
答案 1 :(得分:0)
WITH TeamTree
AS (
SELECT ParentTeam.*, Player.PlayerID AS UrPlayerID, 0 as Level
FROM Team ParentTeam
INNER JOIN Player ON Player.TeamID = ParentTeam.TeamID
WHERE Player.PlayerID IN (SELECT * FROM dbo.Split(@PlayerIDs,','))
UNION ALL
SELECT ChildTeam.*, TeamTree.PlayerID AS PlayerID, TeamTree.Level + 1
FROM Team ChildTeam
INNER JOIN TeamTree TeamTree
ON ChildTeam.ParentTeamID = TeamTree.TeamID /* These were reversed, I think */
AND UrPlayerID=ChildTeam.PlayerID /* ADDED */
)
否则你会得到一个巨大的重复行,比如玩家数量的平方,不是吗?
- (以下评论后) 非常正确,我误读了架构。看,你不需要把玩家带到最后。我认为团队树的安排可能因玩家而有所不同,但事实并非如此。所以
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;
如果您需要更多列,可以使用Team
重新加入。