程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> Mysql樹型結構2種方式及相互轉換

Mysql樹型結構2種方式及相互轉換

編輯:MySQL綜合教程

Mysql樹型結構2種方式及相互轉換


Mysql實現樹型結構,數據庫上常見有2種方式:領接表、預排序遍歷樹(MPTT)。
領接表方式——
主要依賴於一個 parent 字段,用於指向上級節點,將相鄰的上下級節點連接起來,id 為自動遞增自動,parent_id 為上級節點的 id。
領接表方式的優點在於容易理解,代碼也比較簡單明了。缺點則是遞歸中的 SQL 查詢會導致負載變大,特別是需要處理比較大型的樹狀結構的時候,查詢語句會隨著層級的增加而增加,WEB 應用的瓶頸基本都在數據庫方面,所以這是一個比較致命的缺點,直接導致樹結構的擴展困難重重。
排序遍歷樹方式
現在我們來聊聊第二種方式─預排序遍歷樹方式(即通常所說的 MPTT,Modified Preorder Tree Traversal)。此算法是在第一種方式的基礎之上,給每個節點增加一個左、右數字,用於標識節點的遍歷順序,如下圖所示:

vcq9yrXA/Q==" src="http://www.bkjia.com/uploads/allimg/150703/04231513a-0.gif" title="PHP+Mysql樹型結構(無限分類)數據庫設計的2種方式實例" />

從根節點開始左邊為 1,然後下一個節點的左邊為 2,以此類推,到最低層節點之後,最低層節點的右邊為其左邊的數字加 1。順著這些節點,我們可以很容易地遍歷完整個樹。根據上圖,我們對數據表做一些改變,增加兩個字段,lft 和 rgt 用於存儲左右數字( left 和 right 是 MySQL 的保留字,所以改用簡寫)。

可以看出,由於MPTT方式存儲不僅包含隸屬關系,還包括了順序,因此在讀取子樹時不需遞歸,效率大大提高。

下面面討論下如何在這兩著間轉換.

MPTT轉領接表比較容易,只要尋找層級比當前節點小1,且lft<當前節點lft,rgt>當前節點rgt的節點,即為父節點。

領接表轉MPTT,一般直觀想到的是遞歸生成。但是這個不是尾遞歸,遞歸層數有限制, mysql沒有數組自建堆棧要用表,效率很低,怎麼辦?

筆者設計了一個近似遞推的算法,分享一下:

首先確定問題:領接表結構(id,pid),目標MPTT表結構(id,lvl,lft,rgt)。

為處理需要,MPTT表增加cnt、seq字段,用於記錄節點及其子節點的個數、在MPTT中遍歷的序號。

處理過程算法如下:

1】根節點,轉入MPTT表,令lvl=1,lft=1,rgt=null,cnt=null,seq=1;

2】逐層處理p的子節點,lvl+1;

3】從最底層(lvl最大)向上(lvl遞減)處理各層的節點,cnt=子節點的cnt數+1

4】從最上曾(lvl=1)向下(lvl遞增)處理各層的節點,seq=父節點seq+ sum(id小於本節點的兄弟節點的cnt)+1

5】對每一個節點,lft=seq*2-lvl,rgt = lft +cnt *2 -1

處理結束;

此算法已在項目中應用,代碼是有版權的,就不貼了。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved