0

Player という名前の SQL テーブルと、Team という名前の別の SQL テーブルがあります。

  • 各プレーヤーは、外部キーを介してチームに属している必要がありますTeamID
  • 各チームは、再帰フィールドを介して別のチームに属することができますParentTeamID

だからそれは(トップダウン)...

  • チームA
  • チームB
  • チーム76
  • グループ8
  • Player_ME

私の質問は、プレイヤー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 (無限再帰) になることができますが、プレイヤーは 1 つのチームにしか所属できません。

データ構造 チーム: TeamID (PK)、名前、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

したがって、上記のデータを使用すると、両方のプレーヤーが (クエリで) TeamA の「TopLevelTeam」を持っていることを示す必要があります。

4

2 に答える 2

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 に 2 回参加するだけで、プレーヤーのチーム階層内の任意のレベルに移動できます。あなたの場合、2 番目に多いチームに依頼しました: 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
于 2012-07-16T19:47:02.537 に答える
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 */
    )

そうしないと、プレーヤー数の2乗のように、行が大幅に重複しますね。

-(以下のコメントの後)まったく正しいですが、スキーマを読み間違えました。ほら、最後までプレイヤーを連れてくる必要はありません。チームツリーの配置はプレイヤーによって異なるかもしれないと思いましたが、違いはありません。それで

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さらに列が必要な場合は、に再参加できます。

于 2012-07-16T19:10:57.273 に答える