2011-03-08 64 views
0

這個問題類似: How do I query for all the nodes between two nodes in a tree?返回所有節點在許多一對多層次樹

但我有一個閉合(扁平化)表,一個孩子可以有很多家長和ID遍歷不一定按順序。嵌套深度沒有限制。

假設循環引用是不可能的... 我想返回遍歷層次結構所需的所有行。

ParentID ID RowNumber(Reference) 
1   2  1 
2   4  2 
4   3  3 
3   5  4 
1   6  5 
6   7  6 
2   8  7 
3   9  8 
1   8  9 
6   8  10 

鑑於1我將如何編寫一個查詢返回的所有行(得到所有後代relationsips):

下表假設?

同樣地,給定的2我期望行2,3,4,7,8

鑑於6我期望的行6和10

偶爾假陽性是可接受的,因爲在被複制的行結果。缺失的行是不可接受的

實現在MSACCESS和SQL Server 2000+

+0

只是爲了澄清,你的意思是一個孩子可以有很多*父母*而不是許多*祖先*,對嗎?我只問,因爲你發佈的樣本數據沒有顯示任何有多個父母的孩子,但是4,3,5,7有多個祖先。 – mwolfe02 2011-03-08 19:43:50

+0

一個孩子可以有許多父母*和*許多後代。我將添加更多示例 – Matthew 2011-03-08 19:46:18

+0

此外,您希望基於示例數據實現的示例查詢結果將非常有用。一定要使用捕捉所有可能的複雜性的樣本數據(即,具有多個父母的孩子等)。 – mwolfe02 2011-03-08 19:48:03

回答

1

由於你需要在沒有的地方建模數據des可以有多個父母,嵌套集合/ MPTT解決方案將不起作用。另一種選擇是使用closure table

您需要創建舉行對項目的每一個祖先的後代(反之亦然)的附加表:

 
AncID DesID 
    1  2 
    1  6 
    1  4 
    1  8 
    1  7 
    1  3 
    1  5 
    1  9 
    2  4 
    2  8 
    2  3 
    2  5 
    2  9 
    4  3 
    4  5 
    4  9 
    3  5 
    3  9 
    6  7 

那麼你可以使用一個連接來得到你所需要的物品:

SELECT * 
FROM Tbl INNER JOIN Closure ON Tbl.ID=Closure.DesID 
WHERE Closure.AncID = 2 
+0

我對這種方法很熟悉(它被應用於問題中我在OP中鏈接),這將需要額外的數據寫入處理,這是不可取的,我開始相信它是唯一可行的方法來獲得單個查詢的結果,請注意,在我的問題中,它是一張「扁平」的桌子而不是您使用的公認名稱。 – Matthew 2011-03-08 22:34:46

+0

除非您使用具有對相鄰列表模型(Oracle,SQL Server 2005+)的專有支持的數據庫引擎,否則您需要在寫入時或讀取時進行額外的處理。如果您想避免管理其他信息,則可以在讀取時循環訪問記錄集。這將比使用查詢慢,但它將需要較少的維護。這是一個折衷。這取決於你的具體要求。 – mwolfe02 2011-03-09 12:21:31

+0

儘管我不會實現傳遞閉包表,但我將其標記爲答案,因爲它是一個可行的解決方案(不是我打算使用的解決方案) – Matthew 2011-03-31 19:50:00

0

檢查此線程,看看它回答使用ANSI SQL你的問題。基本上Oracle有一個很好的方法來使用CONNECT BY子句來做到這一點,你需要使用ANSI SQL來複制它。 Simulation of CONNECT BY PRIOR of ORACLE in SQL SERVER

+0

CTE在SQL Server 2005中不可用 – RichardTheKiwi 2011-03-08 19:54:37

+1

@Richard Typo我想。不適用於SQL Server 2000. – 2011-03-08 20:05:12

+0

我的思維短路..它應該讀取CTE在* SQL Server 2000中不可用,解決方案鏈接用於* SQL Server 2005.謝謝邁克爾 – RichardTheKiwi 2011-03-08 20:06:31

3

對於SQL Server:Adjacency list vs. nested sets: SQL Server

噴氣/ MS Access中,遞歸查詢是不是一種選擇,所以nested sets將要走的路。對於一個樣本:http://www.mvps.org/access/queries/qry0023.htm

對嵌套組的一些背景:

要實現你需要在你的表中添加和維護兩個附加列一組嵌套的解決方案:LtRt(左,右,分別)。您可以通過執行修改的預定義樹遍歷來爲這些列分配值來填充這些列。這可以通過遞歸功能輕鬆完成。然後,您可以在SELECT時間使用左值和右值來確定後代。

無論何時只要數據發生變化,折衷就需要更多的處理,但在檢索數據時要快得多。

這個概念有點不直觀,肯定有學習曲線,但我個人使用它的效果很好。據我所知,它是在Jet(MS Access數據庫引擎)中僅使用SELECT查詢後完成的唯一方法。

樣品嵌套組解決方案:

ParentID ID Lt Rt RowNumber(Reference) 
Null  1 1 18 0 
1   2 2 13 1 
2   4 3 10 2 
4   3 4 9 3 
3   5 5 6 4 
1   6 14 17 5 
6   7 15 16 6 
2   8 11 12 7 
3   9 7 8 8 

然後拿到ID 2的所有後代:

SELECT * FROM Tbl WHERE Lt Between 2 And 13 

這裏的樹是什麼樣子圖形:

Modified Preorder Tree

+1

仔細檢查後,它看起來像遞歸查詢僅在SQL Server 2005+中可用。 – mwolfe02 2011-03-08 20:05:20

+1

請注意,第一個鏈接還包括SQL Server中的嵌套集的實現,它將在SQL Server 2000中工作。該鏈接中的鄰接列表示例僅適用於SQL Server 2005+。 – mwolfe02 2011-03-08 20:17:02

+0

該樹的圖形表示對於理解Rt/Lt數據非常有幫助......但確定數字是在左邊還是右邊?在你的圖形中,你有兩個左邊的6,左邊的8,左邊的7,左邊的9,...但樹無論數字朝哪方都是可以穿越的......儘管Rt/Lt值是不同。 – Matthew 2011-03-08 21:58:42