2012-07-16 21 views
2

要開始這不是我的同名問題的重複,我只是想不出一個更好的名字爲這個!限制遞歸到一定的水平 - 重複行

我有一個名爲Player的SQL表,另一個名爲Unit。

  • 每個玩家都必須通過外鍵UnitID屬於一個團隊。
  • 每個單元可以通過遞歸字段ParentUnitID屬於另一個Team。
  • 一個ParentUnit可以是一個ParentUnit(無限遞歸),但是一個Player只能屬於一個Team。
  • 一個單位可能有很多孩子

所以它可能是(自上而下)...

  • TeamA(是頂層)
  • TeamB(屬於^^)
  • TeamC(屬於^^)
  • TeamD(屬於^^)
  • PLAYER_1(屬於^^)

我的問題是,如果我獲得Player的PlayerID(該表的PK),獲得特定團隊的最佳方式是什麼?

看我爲數據結構和查詢SQLFiddle:http://sqlfiddle.com/#!3/78965/3

隨着我的數據(從小提琴),我希望能夠得到「TeamB」下的每一個球員,但隨後「Player4」」最重要的單位應該是「TeamC」。爲了做到這一點,我想通過的是「TeamB」的PlayerID和ID。所以我說:「讓所有的球員和頂級單位下TeamB然後過濾掉所有的玩家除了Player4

編輯:我相信上面的段落應改爲:隨着我的數據(從小提琴),我希望能夠建立在「TeamB」下面運行的頂級球隊,對於「TeamB」下面的每個頂級球隊,我想要建立所有爲該球隊效力或低於該球隊效​​力的球員,然後我希望能夠限制玩家到一個或多個具體的球員名單。

正如你可以看到SQLFiddle我回來多行的每個球員,我敢肯定,這是一個快速解決方案,但我不能弄明白。 T帽子就是我在我的小提琴去了,但它的,還有,呃,有點繁瑣... :)

編輯:更多信息:

OK,所以如果想象這是一個存儲過程。

  • 我通過在PlayerIDs 1,2,3,4
  • 我通過在單元ID 2

我希望將返回的數據看起來就像

Player3, TeamC 

只有Player3被返回,因爲它是TeamB(ID 2)的後裔的唯一玩家,並且TeamC被返回,因爲它是Player3所屬的最高級別單元(在UnitID 2之下)。

如果我不是在傳遞:

  • 我通過在PlayerIDs 1,2,3,4
  • 我通過在單元ID 6

我希望

Player1, Team2 
Player2, Team2 
+0

這是你以後:http://sqlfiddle.com/#!3/78965/5 – 2012-07-16 21:35:33

+2

維傑,給你想要作爲表的結果!你的問題是無稽之談。你說*「我希望能夠讓每個玩家都在」TeamB「下,但是」Player4「的頂級單位應該是」TeamC「。爲了做到這一點,我想通過的是PlayerID和ID 「TeamB」,所以我的意思是「讓TeamB下的所有球員和頂級單位,然後濾除除Player4以外的所有球員」。*對不起,但這根本沒有意義,並且與數據和結果無關SQLFiddle。 – 2012-07-16 21:50:09

+0

@SteveKass - 我在這個問題中增加了更多的信息,似乎有點苛刻,把它稱爲廢話,但是我能理解我失去了你的位置!希望我的編輯更有意義,如果不是請解釋哪一部分希望它不是全部!)在具體沒有意義,我會盡我所能進一步解釋。 – Faraday 2012-07-16 22:12:34

回答

2

這個答案已經完全重寫。在任何情況下,原文並不完全適用

我必須更改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單元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) 



這是我原來的答覆。它只適用於單位層次結構限制爲每個單元只允許一個孩子的情況。在這個問題的SQL小提琴例子有3個孩子1號機組,因此,如果對運行1號機組

這裏是一個SQL Fiddle演示該問題它錯誤地返回多行的玩家3,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) 
2
with UnitCTE as (
    select UnitID, 
     Designation, 
     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, 
     c.UnitID, 
     c.Designation, 
     c.TopUnitID, 
     c.TopUnitDesignation, 
     TeamLevel+1 as TeamLevel 
    from Unit t 
    join UnitCTE c 
     on t.ParentUnitID = c.UnitID 
     --WHERE t.UnitID = 1 
), 
x AS (
select Player.PlayerID, 
     pDesignation = Player.Designation, t1.*, 
     rn = ROW_NUMBER() OVER (PARTITION BY Player.PlayerID ORDER BY Player.Designation) 
    from Player 
    join UnitCTE t1 
    on Player.UnitID = t1.UnitID 
    join UnitCTE t2 
    on t1.TopUnitID = t2.TopUnitID 
    and t2.TeamLevel=2 
) 
SELECT * FROM x 
WHERE rn = 1 
    ORDER BY TeamLevel 
+0

雖然這確實解決了有多個記錄的問題,但它沒有解決我張貼在我的下面的段落鏈接到小提琴 – Faraday 2012-07-16 21:51:33

+1

@Vijay很好,因爲史蒂夫建議t他的段落不合邏輯。請顯示樣本數據和期望的結果,而不是給我們提供單詞問題。也請閱讀http://dba.blogoverflow.com/2012/06/help-us-help-you/ - 字問題從來都不是一個好主意。您要求數據人員幫助您解決數據問題;向我們展示數據! – 2012-07-16 22:17:38

+0

我編輯了我的問題以添加更多數據。請大家看看,如果我需要進一步闡述,請告訴我。 – Faraday 2012-07-16 22:20:24