咱們最多見最簡單的方法就是在MySql裏ID ,parentID,name: html
優勢是簡單,結構簡單。
缺點是效率不高,由於每一次遞歸都要查詢數據庫,幾百條數據庫時就不是很快了! node
存儲樹是一種常見的問題,多種解決方案。主要有兩種方法:鄰接表的模型,並修改樹前序遍歷算法。 mysql
咱們將探討這兩種方法的節能等級的數據。我會使用樹從一個虛構的網上食品商店做爲一個例子。這食品商店組織其食品類,經過顏色和類型。這棵樹看起來像這樣: 算法
下面咱們將用另一種方法,這就是預排序遍歷樹算法(modified preorder tree traversal algorithm) 。 sql
這種方法你們可能接觸的比較少,初次使用也不像上面的方法容易理解,可是因爲這種方法不使用遞歸查詢算法,有更高的查詢效率。 數據庫
咱們首先將多級數據按照下面的方式畫在紙上,在根節點Food的左側寫上 1 而後沿着這個樹繼續向下 在 Fruit 的左側寫上 2 而後繼續前進, 沿着整個樹的邊緣給每個節點都標上左側和右側的數字。最後一個數字是標在Food 右側的 18。 在下面的這張圖中你能夠看到整個標好了數字的多級結 構。(沒有看懂?用你的手指指着數字從1數到18就明白怎麼回事了。還不明白,再數一遍,注意移動你的手指)。 數據結構
這些數字標明瞭各個節點之間的關係,」Red」的號是3和6,它是 」Food」 1-18 的子孫節點。 一樣,咱們能夠看到 全部左值大於2和右值小於11的節點 都是」Fruit」 2-11 的子孫節點 函數
如圖所示: ui
這樣整個樹狀結構能夠經過左右值來存儲到數據庫中。繼續以前,咱們看一看下面整理過的數據表。 spa
注意:因爲」left」和」right」在 SQL中有特殊的意義,因此咱們須要用」lft」和」rgt」來表示左右字段。 另外這種結構中再也不須要」parent」字段來表示樹狀結構。也就是 說下面這樣的表結構就足夠了。
SELECT * FROM tree WHERE lft BETWEEN 2 AND 11;
看到了吧,只要一個查詢就能夠獲得全部這些節點。爲了可以像上面的遞歸函數那樣顯示整個樹狀結構,咱們還須要對這樣的查詢進行排序。用節點的左值進行排序:
SELECT * FROM tree WHERE lft BETWEEN 2 AND 11 ORDER BY lft ASC;
那麼某個節點到底有多少子孫節點呢?很簡單,子孫總數=(右值-左值-1)/2
descendants = (right – left - 1) / 2 ,若是不是很清楚這個公式,那就去翻下書,咱們在上數據結構寫的很清楚!
添加同一層次的節點的方法以下:
LOCK TABLE nested_category WRITE;
SELECT @myRight := rgt FROM nested_category
WHERE name = ‘Cherry’;
UPDATE nested_category SET rgt = rgt + 2 WHERE rgt > @myRight;
UPDATE nested_category SET lft = lft + 2 WHERE lft > @myRight;
INSERT INTO nested_category(name, lft, rgt) VALUES(‘Strawberry’, @myRight + 1, @myRight + 2);
UNLOCK TABLES;
LOCK TABLE nested_category WRITE;
SELECT @myLeft := lft FROM nested_category
WHERE name = ‘Beef’;
UPDATE nested_category SET rgt = rgt + 2 WHERE rgt > @myLeft ;
UPDATE nested_category SET lft = lft + 2 WHERE lft > @myLeft ;
INSERT INTO nested_category(name, lft, rgt) VALUES(‘charqui’, @myLeft + 1, @myLeft + 2);
UNLOCK TABLES;
SELECT CONCAT( REPEAT( ‘ ‘, (COUNT(parent.name) – 1) ), node.name) AS name
FROM nested_category AS node,
nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
GROUP BY node.name
ORDER BY node.lft;
LOCK TABLE nested_category WRITE;
SELECT @myLeft := lft, @myRight := rgt, @myWidth := rgt – lft + 1
FROM nested_category
WHERE name = ‘Cherry’;
DELETE FROM nested_category WHERE lft BETWEEN @myLeft AND @myRight;
UPDATE nested_category SET rgt = rgt – @myWidth WHERE rgt > @myRight;
UPDATE nested_category SET lft = lft – @myWidth WHERE lft > @myRight;
UNLOCK TABLES;
這種方式就是有點難的理解,可是適合數據量很大規模使用,查看全部的結構只須要兩條SQL語句就能夠了,在添加節點和刪除節點的時候略顯麻煩,不過相對於 效率來講仍是值得的,此次發現讓我發現了數據庫結構真的頗有用,可是我在學校學的樹基本上都忘記了,此次遇到這個問題才應用到項目中!
參考文章:
http://dev.mysql.com/tech-resources/articles/hierarchical-data.html
http://www.sitepoint.com/article/hierarchical-data-database/3/