關系型數據庫樹形關系存儲-閉包表

前言

在關系型數據庫中讲竿,有一種邏輯關系比較難處理烧给,這種就是樹形結構。目前有很多主流的處理方案缝龄,比如說直接在業(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<Releation> 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))
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末臭家,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子方淤,更是在濱河造成了極大的恐慌钉赁,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件携茂,死亡現場離奇詭異你踩,居然都是意外死亡,警方通過查閱死者的電腦和手機邑蒋,發(fā)現死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門姓蜂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人医吊,你說我怎么就攤上這事钱慢。” “怎么了卿堂?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵束莫,是天一觀的道長懒棉。 經常有香客問我,道長览绿,這世上最難降的妖魔是什么策严? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮饿敲,結果婚禮上妻导,老公的妹妹穿的比我還像新娘。我一直安慰自己怀各,他們只是感情好倔韭,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著瓢对,像睡著了一般寿酌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上硕蛹,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天醇疼,我揣著相機與錄音,去河邊找鬼法焰。 笑死秧荆,一個胖子當著我的面吹牛,可吹牛的內容都是我干的壶栋。 我是一名探鬼主播辰如,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼贵试!你這毒婦竟也來了琉兜?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤毙玻,失蹤者是張志新(化名)和其女友劉穎豌蟋,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體桑滩,經...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡梧疲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了运准。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片幌氮。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖胁澳,靈堂內的尸體忽然破棺而出该互,到底是詐尸還是另有隱情,我是刑警寧澤韭畸,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布宇智,位于F島的核電站蔓搞,受9級特大地震影響,放射性物質發(fā)生泄漏随橘。R本人自食惡果不足惜喂分,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望机蔗。 院中可真熱鬧蒲祈,春花似錦、人聲如沸蜒车。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽酿愧。三九已至,卻和暖如春邀泉,著一層夾襖步出監(jiān)牢的瞬間嬉挡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工汇恤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留庞钢,地道東北人。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓因谎,卻偏偏與公主長得像基括,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子财岔,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內容