mysql 存树 闭包表_关系型数据库树形关系存储-闭包表
前言
在關系型數據庫中,有一種邏輯關系比較難處理,這種就是樹形結構。目前有很多主流的處理方案,比如說直接在業(yè)務表中存儲上一級id,這樣就可以用遞歸查詢SQL的形式找到某一節(jié)點的父節(jié)點,子節(jié)點,或者兄弟節(jié)點。注意,是遞歸查詢!由于這種father_id的關系鍵是存儲在業(yè)務表中,那么遞歸查詢肯定對性能有影響。如果業(yè)務表比較小,是可以用這種方法,表結構簡單,維護起來比較簡單,也很直觀。但是業(yè)務表如果是百萬級別的,這種方式就不太合適了。
現在有另外一種方法,新建一個維護關系的表:閉包表,這種方式是一種以空間換取時間的方法。下面解釋一下閉包表如何運作的。
實戰(zhàn)
假設,目前存在如下樹形結構
樹形關系
第一步,新增一個關系表Releation
create table releation(
ancestor varchar
descendant varchar
distacne int
)
其中每一條記錄維護一段關系,圖示中的關系可以這樣維護,如下
表中記錄
首先,我們來滿足查詢,即可以查詢某一個節(jié)點的父節(jié)點,子節(jié)點,等等,以B節(jié)點為例子
B的所有子孫
select r.descendant from releation r where r.ancestor='B' and r.distacne>0
B的兒子
select r.descendant from releation r where r.ancestor='B' and r.distacne=1
B的第幾代(n)孫
select r.descendant from releation r where r.ancestor='B' and r.distacne=n
B的父親
select r.ancestor from releation r where r.descendant='B' and r.distacne=1
B的所有祖先
select r.ancestor from releation r where r.descendant='B' and r.distacne>0
B的兄弟也包括自己(找到B的父親,就能找到他的兄弟)
select r.descendant from releation r left join releation r1 on r1.ancestor = r.descendant
and r1.descendant='B' and r1.distacne=1
查詢所有的子節(jié)點
select ancestor max(distacne) dis from releation group by ancestor having dis=0
然后是新增節(jié)點
即為給某一個節(jié)點新增子節(jié)點,假設該節(jié)點還是B,現在給B節(jié)點新增一個子節(jié)點E
首先,把自己新增進去,SQL:
insert into releation values('E','E',0);
然后找到E的祖先,那么現在E的祖先是B的祖先加上B自己,然后告訴這些祖先們,他們新增了一個后代
通過找祖先的SQL,我們找到了B的祖先,A,那么E的祖先就是B和A
insert into releation values('A','E',2);
insert into releation values('B','E',1);
那么我們可以看出,新增子節(jié)點,除了新增自己以外,還需要通知祖先,并讓祖先保存自己,下面提供一個偽碼,實現該功能
public insert(Node a,Node b){
//1.將自己記錄下來
conn.excuteSql(insert into releation values(a,a,0));
//2.查找a的祖先和自己,并告知他們,他們新增的子孫b
List ancestors = conn.excuteSql(select r.ancestor from releation r where r.descendant=a order by distacne);
for(Releation r : ancestors){
conn.excuteSql(insert into releation values(r.ancestor,b,r.distacne+1))
}
}
總結
以上是生活随笔為你收集整理的mysql 存树 闭包表_关系型数据库树形关系存储-闭包表的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: assembly 输出ab中所有数_.N
- 下一篇: python中如何定义函数的传入参数是o