gpt4 book ai didi

sql - 将递归限制到某个级别 - 重复行

转载 作者:行者123 更新时间:2023-12-04 18:16:44 25 4
gpt4 key购买 nike

首先,这不是我的另一个同名问题的重复,我只是想不出一个更好的名字!

我有一个名为 Player 的 SQL 表和另一个名为 Unit 的 SQL 表。

  • 每个玩家必须通过外键 UnitID 属于一个团队。
  • 每个单元可以通过递归字段 ParentUnitID 属于另一个团队。
  • ParentUnit 可以是 ParentUnit(无限递归),但 Player 只能属于一个 Team。
  • 一个单元可能有很多 child

  • 所以它可能是(自上而下)......
  • TeamA(是顶级)
  • TeamB (属于^^)
  • TeamC (属于^^)
  • TeamD(属于^^)
  • Player_1 (属于^^)

  • 我的问题是,如果给我一个 Player's PlayerID(该表的 PK),那么获得特定团队的最佳方法是什么?

    有关数据、结构和查询,请参见我的 SQLFiddle: http://sqlfiddle.com/#!3/78965/3

    使用我的数据(来自 fiddle ),我希望能够让每个玩家都在“TeamB”之下,但是“Player4”的顶级单位应该是“TeamC”。为此,我只想传入 PlayerID 和“TeamB”的 ID。所以我的意思是“让 TeamB 下的所有玩家和顶级单位,然后过滤掉除 Player4 之外的所有玩家。

    编辑:我相信上面的段落应该是: 使用我的数据(来自 fiddle ),我希望能够建立在“TeamB”以下比赛的顶级球队。然后,对于“TeamB”以下的每个顶级球队,我想建立所有为该球队效力或低于该球队的球员。然后,我希望能够将玩家列表限制为一个或多个特定玩家。

    正如您在 SQLFiddle 中看到的那样,我为每个玩家返回了多行,我确信这是一个快速修复,但我无法弄清楚......这就是我在 fiddle 中想要的,但它是,好吧,呃,有点繁琐... :)

    编辑:更多信息:

    好的,所以如果想象这是一个存储过程。
  • 我传入 PlayerIDs 1,2,3,4
  • 我传入 UnitID 2

  • 我希望返回的数据看起来像
    Player3, TeamC

    仅返回 Player3,因为它是 TeamB(ID 2)的唯一后代,而 TeamC 是因为它是 Player3 所属的最高级别单元(低于 UnitID 2)而返回。

    如果我改为通过:
  • 我传入 PlayerIDs 1,2,3,4
  • 我传入 UnitID 6

  • 我希望
    Player1, Team2
    Player2, Team2

    最佳答案

    这个答案已被完全重写。原版在所有情况下都无法正常工作

    我必须更改 CTE 以将每个单元的完整单元层次结构表示为可能的根(顶部单元)。它允许一个真正的层次结构,每个单元有多个子级。

    我扩展了这个 SQL Fiddle 中的示例数据将一名球员分配到第 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 中嵌入了 Unit ID 标准。 CTE 仅计算以父 ID 为所选单元 ID(在本例中为 1)的单元为根的层次结构
    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)



    这是我的原始答案。 它仅在单元层次结构被限制为每个单元只允许一个 child 时才有效。问题中的 SQL Fiddle 示例有 Unit 1 的 3 个子项,因此如果针对 Unit 1 运行,它会错误地为玩家 3、5 和 6 返回多行

    这是 SQL Fiddle这说明了问题。
    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)

    关于sql - 将递归限制到某个级别 - 重复行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11512805/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com