超贊 ! 老外的一種避免遞歸查詢所有子部門的樹數(shù)據(jù)表設(shè)計(jì)與實(shí)現(xiàn)!
點(diǎn)擊上方“碼農(nóng)突圍”,馬上關(guān)注
這里是碼農(nóng)充電第一站,回復(fù)“666”,獲取一份專屬大禮包
真愛,請(qǐng)?jiān)O(shè)置“星標(biāo)”或點(diǎn)個(gè)“在看”

來源:https://sourl.cn/aCCTwr
問題來了
查出所有子孫部門
查詢子孫部門總數(shù)
判斷是否葉子節(jié)點(diǎn)
要不試試這個(gè)方法?
查出所有子孫部門
查詢子孫部門總數(shù)
判斷是否葉子節(jié)點(diǎn)
其他基本操作
完結(jié)


id??????????部門編號(hào)
name????????部門名稱
level???????所在樹層級(jí)
parent_id???上級(jí)部門編號(hào)
| 問題來了
例如:PM加了以下需求:
查出指定部門下所有子孫部門 查詢子孫部門總數(shù) 判斷節(jié)點(diǎn)是否葉子節(jié)點(diǎn)
查出所有子孫部門
查詢子孫部門總數(shù)
判斷是否葉子節(jié)點(diǎn)
| 要不試試這個(gè)方法?



查出所有子孫部門
SET?@lft?:=?9;
SET?@rgt?:=?18;
SELECT?*?FROM?department?WHERE?lft?BETWEEN?@lft?AND?@rgt?ORDER?BY?lft?ASC;
/*例子中用BETWEEN將被查部門本身也查了出來。實(shí)際中可以用大于小于*/完美~
查詢子孫部門總數(shù)
行政總監(jiān)的子孫部門數(shù)?=?(18?-?9?-?1)?/?2?=?4
董事長(zhǎng)的子孫部門數(shù)?=?(20?-?1?-?1)?/?2?=?9
會(huì)計(jì)的子部門數(shù)?=??(14?-?13?-?1)?/?2?=?0
可以數(shù)數(shù)看,確實(shí)沒錯(cuò)哦~
判斷是否葉子節(jié)點(diǎn)
| 其他基本操作
新增部門

SET?@lft?:=?7;/*新部門的左值*/
SET?@rgt?:=?8;/*新部門的左值*/
SET?@level?:=?5;/*新部門的層級(jí)*/
begin;
/*將插入的后續(xù)邊緣的節(jié)點(diǎn)左右數(shù)+2*/
UPDATE?department?SET?lft=lft+2?WHERE?lft?>?@lft;
UPDATE?department?SET?rgt=rgt+2?WHERE?rgt?>=?@lft;
/*插入數(shù)據(jù)*/
INSERT?INTO?department(name,lft,rgt,level)?VALUES('新部門',@lft,@rgt,level);
/*新增影響行數(shù)為0時(shí),必須回滾*/
commit;
/*rollback;*/
刪除部門

SET?@lft?:=?7;/*要?jiǎng)h除的節(jié)點(diǎn)左值*/
SET?@rgt?:=?8;/*要?jiǎng)h除的節(jié)點(diǎn)右值*/
begin;
UPDATE?department?SET?lft=lft-2?WHERE?lft?>?@lft;
UPDATE?department?SET?rgt=rgt-2?WHERE?rgt?>?@lft;
/*刪除節(jié)點(diǎn)*/
DELETE?FROM?department?WHERE?lft=@lft?AND?rgt=@rgt;
/*刪除影響行數(shù)為0時(shí),必須回滾*/
commit;
/*rollback*/
查詢直接子部門

SET?@level?:=?2;/*總經(jīng)理的level*/
SET?@lft?:=?2;/*總經(jīng)理的左值*/
SET?@rgt?:=?19;/*總經(jīng)理的右值*/
SELECT?*?FROM?department?WHERE?lft?>?@lft?AND?rgt?@rgt?AND?level?=?@level+1;
查詢祖鏈路徑
SET?@lft?:=?3;/*產(chǎn)品部左值*/
SET?@rgt?:=?8;/*產(chǎn)品部右值*/
SELECT?*?FROM?department?WHERE?lft?@lft?AND?rgt?>?@rgt?ORDER?BY?lft?ASC;
樹形數(shù)據(jù)展示(JS示例)
let?list?=?[//模擬sql查出來的列表。
????{id:1,name:'root',lft:1,rgt:8,level:1},
????{id:2,name:'child',lft:2,rgt:7,level:2},
????{id:3,name:'grandson',lft:3,rgt:4,level:3},
????{id:4,name:'grandson2',lft:5,rgt:6,level:3}
];
let?rights?=?[]?/*類似于一個(gè)棧結(jié)構(gòu)(后進(jìn)先出)*/
let?mp?=?{}
//list.sort((a,b)?=> a.lft - b.lft)//如果你在sql中沒有進(jìn)行排序,需要在這里給他排序。
list.forEach(item?=>?{
????if(rights.length?>?0)?{
????????while(rights[rights.length-1]?????????????rights.splice(-1,?1)//從rights末尾去除
????????}
????}
????let?_level?=?rights.length;
????item._level?=?_level;
????mp[_level]?=?item.id
????item.parent_id?=?_level?-?1?in?mp???mp[_level?-?1]?:?null;//計(jì)算出上級(jí)部門編號(hào)
????item.is_leaf?=?item.lft?===?item.rgt?-?1;//判斷是否葉子部門
????rights.push(item.rgt)
})
/*上級(jí)部門計(jì)算出來了,和存parent_id的效果就一樣了,后面只需要遞歸即可*/
/*遞歸函數(shù)?示例*/
let?recursive?=?(_list,?parent_id?=?null)?=>?{
????let?_tree?=?[];
????_list.forEach(item?=>?{
????????if(item.parent_id?==?parent_id)?{
????????????let?childs?=?recursive(_list,?item.id)
????????????_tree.push({
????????????????...item,
????????????????children:?childs.length?>?0???childs?:?(item.isLeaf???null?:?[])
????????????})
????????}
????})
????return?_tree
}
console.log(recursive(list))
| 完結(jié)
(完)
碼農(nóng)突圍資料鏈接
1、臥槽!字節(jié)跳動(dòng)《算法中文手冊(cè)》火了,完整版 PDF 開放下載!
2、計(jì)算機(jī)基礎(chǔ)知識(shí)總結(jié)與操作系統(tǒng) PDF 下載
3、艾瑪,終于來了!《LeetCode Java版題解》.PDF
4、Github 10K+,《LeetCode刷題C/C++版答案》出爐.PDF歡迎添加魚哥個(gè)人微信:smartfish2020,進(jìn)粉絲群或圍觀朋友圈。
評(píng)論
圖片
表情
