2009-08-26 94 views
1

我有一個數據庫表(sqlite)包含形成樹層次結構的項目。每個項目的父項都有一個id字段(本身)和一個parentId。現在給出一個項目,我必須檢索從根源到項目的整個鏈。我需要多少SQL查詢?

基本上在僞碼算法看起來像:

  1. 光標項
  2. 檢索parentItem爲光標由parentId的
  3. 如果parentItem不rootItem,然後光標= parentItem和GOTO 2.

所以我必須爲每個項目執行SQL SELECT查詢。

是否有可能通過執行只有一個SQL查詢檢索整個鏈rootItem - > ... - >項?

回答

0

不符合ANSI標準的SQL它不是,沒有。那麼,這不是真的。您可以執行左外連接並放入足夠的深度以覆蓋可能的最大深度,但除非您限制最大深度幷包含多個連接,否則它不會始終有效。

如果你的行集合足夠小(比如小於1000),只需要檢索它們然後找出它們。它很可能會比單遍讀取更快。

您可以批處理父級遍歷。有如下查詢:

SELECT t1.id id1, t1.parent parent1, 
     t2.id id2, t2.parent parent2, 
     t3.id id3, t3.parent parent3, 
     t4.id id4, t4.parent parent4, 
     t5.id id5, t5.parent parent5 
FROM mytable t1 
LEFT OUTER JOIN mytable t2 ON t1.parent = t2.id 
LEFT OUTER JOIN mytable t3 ON t2.parent = t3.id 
LEFT OUTER JOIN mytable t4 ON t3.parent = t4.id 
LEFT OUTER JOIN mytable t5 ON t4.parent = t5.id 
WHERE t1.id = 1234 

並將其擴展到任何你想要的數字。如果最後檢索到的父項不爲空,那麼您不在樹的頂部,因此再次運行查詢。這種方式,你應該希望減少到1-2往返。

除此之外,你可以看看在ID中編碼數據的方式。這是不推薦,但如果你限制,比方說,每個節點有100個孩子,你可以這麼說,一個ID 10030711節點有10路 - > 03 - > 07 - > 11這當然有其他的問題(如最大ID的長度),當然它是hacky。

另外值得一提的是,有在SQL分層數據兩種基本模式。鄰接列表和嵌套集合。你的方式(這很常見)是一個鄰接集。雖然嵌套集合並不能真正幫助解決這種情況,但插入操作很複雜。

+0

不幸的是我的組行是合理的大,甚至不斷增加。 – 2009-08-26 15:33:53

2

有很多在數據庫中組織hierarchial數據的創造性的方法,但始終我覺得最簡單帶回在非分層格式的數據,然後以編程匹配父和子記錄。

的努力總額:1個查詢+ 1個計劃通過您的數據集以創建層次結構。


替代做法:

我在有限的成功,過去使用這種方法。您可以使用一個varchar(max)列如下存儲每個項目的路徑在你的樹:

ID ParentID Path 
-- -------- ---- 
1  null  1/ 
2  1   1/2/ 
3  null  3/ 
4  2   1/2/4/ 
5  4   1/2/4/5/ 
6  null  6/ 
7  5   1/2/4/5/7/ 
9  5   1/2/4/5/9/ 

從這一點出發,讓所有在ID = 5的節點是非常簡單的:

SELECT * 
FROM table 
WHERE Path like (SELECT Path FROM Table WHERE ID = 5) + '%' 
+0

不錯的技術,我會+1,但我在幾個小時內沒有投票。你爲什麼說**有限**成功壽? – 2009-08-26 16:51:33

+0

爲什麼不只是SELECT * FROM表WHERE路徑LIKE'%/ 5 /%'; ? – 2009-08-26 16:55:34

+0

@eyze:當然,這也可以工作:)但是,在幾乎所有數據庫實現中,數據庫都不能使用以通配符開頭的類似表達式的索引。請參閱SQLite文檔(http://www.sqlite.org/optoverview.html):「由LIKE或GLOB運算符組成的術語有時可用於約束索引。這種用法有許多條件:[.. 。] LIKE或GLOB的右側必須是不以通配符開頭的字符串文字「。我不確定上面的代碼會使用索引eithers,因爲它不是字符串文字。因人而異。 – Juliet 2009-08-26 17:17:55