資源描述:
《php左右值無限分類》由會員上傳分享,免費在線閱讀,更多相關(guān)內(nèi)容在行業(yè)資料-天天文庫。
1、采用左右值編碼來存儲無限分級樹形結(jié)構(gòu)的數(shù)據(jù)庫表設(shè)計之前我介紹過一種按位數(shù)編碼保存樹形結(jié)構(gòu)數(shù)據(jù)的表設(shè)計方法,詳情見:淺談數(shù)據(jù)庫設(shè)計技巧(上)該設(shè)計方案的優(yōu)點是:只用一條查詢語句即可得到某個根節(jié)點及其所有子孫節(jié)點的先序遍歷。由于消除了遞歸,在數(shù)據(jù)記錄量較大時,可以大大提高列表效率。但是,這種編碼方案由于層信息位數(shù)的限制,限制了每層能所允許的最大子節(jié)點數(shù)量及最大層數(shù)。同時,在添加新節(jié)點的時候必須先計算新節(jié)點的位置是否超過最大限制。上面的設(shè)計方案必須預(yù)先設(shè)定類別樹的最大層數(shù)以及最大子節(jié)點數(shù),不是無限分級,在某些場合并不能采用,那么還有更完美的解決方案嗎?通過google的搜索,我又探
2、索到一種全新的無遞歸查詢,無限分級的編碼方案——左右值。原文的程序代碼是用php寫的,但是通過仔細(xì)閱讀其數(shù)據(jù)庫表設(shè)計說明及相關(guān)的sql語句,我徹底弄懂了這種巧妙的設(shè)計思路,并在這種設(shè)計中新增了刪除節(jié)點,同層平移的需求(原文只提供了列表及插入子節(jié)點的sql語句)。下面我力圖用比較簡短的文字,少量圖表,及相關(guān)核心sql語句來描述這種設(shè)計方案:首先,我們弄一棵樹作為例子:商品
3、---食品
4、????
5、---肉類
6、????
7、????
8、--豬肉
9、????
10、---蔬菜類
11、??????????
12、--白菜
13、---電器?????
14、--電視機(jī)?????
15、--電冰箱?采用左右值編碼的保存該樹的數(shù)據(jù)記
16、錄如下(設(shè)表名為tree):Type_idNameLftRgt1商品1182食品2113肉類364豬肉455蔬菜類7106白菜897電器12178電視機(jī)13149電冰箱1516?第一次看見上面的數(shù)據(jù)記錄,相信大部分人都不清楚左值(Lft)和右值(Rgt)是根據(jù)什么規(guī)則計算出來的,而且,這種表設(shè)計似乎沒有保存父節(jié)點的信息。下面把左右值和樹結(jié)合起來,請看: ?1商品18 +---------------------------------------+???????????????2食品11?????????????????????????????????
17、??12電器17?????????+-----------------+????????????????????+---------------------+????3肉類6?????????7蔬菜類10?????????13電視機(jī)14??????15電冰箱16???4豬肉5??????????8白菜9請用手指指著上圖中的數(shù)字,從1數(shù)到18,學(xué)習(xí)過數(shù)據(jù)結(jié)構(gòu)的朋友肯定會發(fā)現(xiàn)什么吧?對,你手指移動的順序就是對這棵樹的進(jìn)行先序遍歷的順序。接下來,讓我講述一下如何利用節(jié)點的左右值,得到該節(jié)點的父節(jié)點,子孫節(jié)點數(shù)量,及自己在樹中的層數(shù)。?假定我們要對節(jié)點“食品”及其子孫節(jié)點進(jìn)行先序遍歷
18、的列表,只需使用如下一條sql語句:select*fromtreewhereLftbetween2and11orderbyLftasc查詢結(jié)果如下:Type_idNameLftRgt2食品2113肉類364豬肉455蔬菜類7106白菜89?那么某個節(jié)點到底有多少子孫節(jié)點呢?很簡單,子孫總數(shù)=(右值-左值-1)/2?以節(jié)點“食品”舉例,其子孫總數(shù)=(11-2-1)/2=4?同時,我們在列表顯示整個類別樹的時候,為了方便用戶直觀的看到樹的層次,一般會根據(jù)節(jié)點所處的層數(shù)來進(jìn)行相應(yīng)的縮進(jìn),那么,如何計算節(jié)點在樹中的層數(shù)呢?還是只需通過左右值的查詢即可,以節(jié)點“食品”舉例,sql語句如
19、下:selectcount(*)fromtreewherelft<=2andrgt>=11為了方便列表,我們可以為tree表建立一個視圖,添加一個層數(shù)列,該類別的層數(shù)可以寫一個自定義函數(shù)來計算。該函數(shù)如下:CREATE?FUNCTION?dbo.CountLayer(????????@type_id?int)RETURNS?intASbegin????declare?@result?int????set?@result=0????declare?@lft?int????declare?@rgt?int????if?exists?(select?1?from?tree?wher
20、e?type_id=@type_id)????begin????????select?@lft=lft,@rgt=rgt?from?tree?where?type_id=@type_id????????select?@result?=?count(*)?from?tree?where?lft?<=?@lft?and?rgt?>=?@rgt????end????????return?@resultendGO然后,我們建立如下視圖:CREATE?VIEW?dbo.TreeViewASSELECT?type_