环球热头条丨一种避免递归查询的树状数据表设计与实现
通常树形结构的存储,是在子节点上存储父节点的编号来确定各节点的父子关系,例如这样的组织结构:
通常树形结构的存储,是在子节点上存储父节点的编号来确定各节点的父子关系,例如这样的组织结构:
与之对应的表数据(department):
部门表结构(department)
(相关资料图)
id部门编号name部门名称level所在树层级parent_id上级部门编号
这样的方式很不错,可以很直观的体现各个节点之间的关系,通常可以满足大多数需求。但是当业务需求变得多了,数据量庞大了,这样的方式就不再适合用于生产。
例如:PM加了以下需求:
查出指定部门下所有子孙部门查询子孙部门总数判断节点是否叶子节点使用指定部门编号,一层一层使用递归往下查,可能是多数人会想到的方法。尽管在mysql8.0支持了 cte(公共表表达式),递归效率比传统递归方式有明显提升,但是查询效率仍会随着部门树层级深度的提高而变差。
另外一种方法,一次性查出所有数据,放入内存中处理(数据量少时,可以选用。数据量多,不怕挨打的人也可以选这种)~
递归查询每一层的数量,最后相加。
方法1:可以加字段isLeaf的方式,来表示这个节点是否是叶子节点。
方法2:直接通过查询parent_id=当前id的count是否大于0,大于0表示不是叶子节点,等于0表示为叶子节点。
在日常中,可能会经常使用上述类似方法去解决类似的问题,但我觉得这样的方法在效率上不是最优解。于是乎开始查找更好的方案去解决这些问题。
直到后面查到国外一博客中,见到了所谓的《改进后的先序树遍历》文章(天哪,竟然是一篇2003年发表的文章)~
他具体是怎么做的呢?
还是回到刚刚的组织架构
我们从根节点开始,给董事长左值设为1,下级部门总经理左值设为2,以此类推地沿着边缘开始遍历,给每个节点加上左值,遇到叶子节点处给节点加上右值,再继续向上沿着边缘继续遍历,遍历结束回到根节点右侧,你将得到类似这样的结构。
遍历完后每一个节点都有与之对应的左右值。这个时候可以去除parent_id字段,添加lft,rgt,来存储左右值。
数据和结构准备完毕,我们来试试操作解决上面的需求~
根据当前表结构的规律,可以发现,要想查出所有子孙部门,只要查左值在 被查寻部门的左\右数之间的节点,查出来都是他的子节点。例如:查询行政总监的所有子部门,行政总监的左右数是9和18,因此只需要用9和18做lft字段的between查询,查询出的结果就是【被查部门本身数据和所有子孙部门】;
SET@lft:=9;SET@rgt:=18;SELECT*FROMdepartmentWHERElftBETWEEN@lftAND@rgtORDERBYlftASC;/*例子中用BETWEEN将被查部门本身也查了出来。实际中可以用大于小于*/完美~
到这里可能会说,需求1都解决了,查总数自然也就解决了,直接上select count就可以了,确实没有错,但是没有那个必要,因为有个简单公式可以直接计算。
公式:总数 = (右值 - 左值 - 1) / 2
例如:
行政总监的子孙部门数=(18-9-1)/2=4董事长的子孙部门数=(20-1-1)/2=9会计的子部门数=(14-13-1)/2=0可以数数看,确实没错哦~
通过有了上述计算公式算总数的经验后,现在判断是否叶子节点,有的小伙伴已经知道了怎么做,那就是:
右值 - 1 == 左值那他就是叶子节点,或者左值 + 1 == 右值那他就是叶子节点,反之则不是叶子节点。
例如:
设计部,5 - 1 == 4,因此他是叶子节点。
董事长,20 - 1 != 1,因此他不是叶子节点。
至此已经完美的解决了上述需求问题,接下来再尝试一下业务的基本操作。
当新增一个部门时,需要对新增节点位置的后续边缘进行加2操作,因为每一个节点有左右两个数值。这个操作通常需要放到事务中进行处理。例如:在研发部门下添加一个新部门:
对应sql:
SET@lft:=7;/*新部门的左值*/SET@rgt:=8;/*新部门的左值*/SET@level:=5;/*新部门的层级*/begin;/*将插入的后续边缘的节点左右数+2*/UPDATEdepartmentSETlft=lft+2WHERElft>@lft;UPDATEdepartmentSETrgt=rgt+2WHERErgt>=@lft;/*插入数据*/INSERTINTOdepartment(name,lft,rgt,level)VALUES("新部门",@lft,@rgt,level);/*新增影响行数为0时,必须回滚*/commit;/*rollback;*/
删除部门与新增部门类似,不同的是需要对删除节点的后续边缘节点减2操作。例如:删除刚刚添加的新部门:
对应sql
SET@lft:=7;/*要删除的节点左值*/SET@rgt:=8;/*要删除的节点右值*/begin;UPDATEdepartmentSETlft=lft-2WHERElft>@lft;UPDATEdepartmentSETrgt=rgt-2WHERErgt>@lft;/*删除节点*/DELETEFROMdepartmentWHERElft=@lftANDrgt=@rgt;/*删除影响行数为0时,必须回滚*/commit;/*rollback*/
查询某部门的直接子部门(即不包含孙子部门),例如:查询总经理下的直接子部门。正常需要返回产品部和行政总监
对应的sql
SET@level:=2;/*总经理的level*/SET@lft:=2;/*总经理的左值*/SET@rgt:=19;/*总经理的右值*/SELECT*FROMdepartmentWHERElft>@lftANDrgt<@rgtANDlevel=@level+1;
查询某部门的祖链路径。例如:查询产品部的祖链路径,正常需要返回董事长,总经理
SET@lft:=3;/*产品部左值*/SET@rgt:=8;/*产品部右值*/SELECT*FROMdepartmentWHERElft<@lftANDrgt>@rgtORDERBYlftASC;
letlist=[//模拟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}];letrights=[]/*类似于一个栈结构(后进先出)*/letmp={}//list.sort((a,b)=> a.lft - b.lft)//如果你在sql中没有进行排序,需要在这里给他排序。list.forEach(item=>{if(rights.length>0){while(rights[rights.length-1]{let_tree=[];_list.forEach(item=>{if(item.parent_id==parent_id){letchilds=recursive(_list,item.id)_tree.push({...item,children:childs.length>0?childs:(item.isLeaf?null:[])})}})return_tree}console.log(recursive(list))
在我目前看来,这个方法的唯一缺点就是,每一次的新增或删除,操作节点的后续边缘走到的节点都要加/减2操作。
关键词:
通常树形结构的存储,是在子节点上存储父节点的编号来确定各节点的父子关系,例如这样的组织结构:
新增9种颜色,分别是黑色、皇家银、开罗金、普鲁士灰、凯撒金、极地白、橡木棕、罗马季红和流沙金。新大众迈腾的设计比较沉稳大
天津北方网讯:就业时遇到“特别条款”、想变美遭遇医美陷阱、家庭暴力、婚姻纠纷……女性在工作生活中可能会遇到种种障碍。河北区检察院充分
1、Windows的一般配用的是自己的WinRAR,但这个解压较慢,而且是收费的。2、到了30天你在使用他就会一直有收费提示,除非你卸载或者破解它!你
去年为消费者挽回经济损失超45亿元(主题)人民日报海外版北京3月17日电(记者孔德晨)记者16日从国家市场监督管理总局获悉,2022年,全国市场
1、展开1全部巴西的位置:大部分地区位于赤道至南回归线之间,东临大西洋。2、地形:主要有亚马孙平原、巴西高原,东南部地
油价最新消息
荣耀EarBuds2SE是一款降噪耳机,性能出众,一定会给朋友带来极其舒适的音质。那么,朋友们在这款耳机中有没有非常方便
是内部发热反应产生的气体,暖宝宝的发热原理是氧化反应产热,一般质量可以的暖宝宝是多层透气包装,所谓透气只是相对于密封状态而言,实际为
周五市场呈现冲高回落的格局,投资者可以看到,早盘沪指高开18点于3245点,创业板高开18点于2320点,早盘市场高开以后冲高,遇阻3280点附近反
股票突破年线则意味着市场上的多空较量中,多方力量占主导地位,股价在多方力量的推动下,可能会继续上涨,是一种后市看涨的信号。资金流向数
近年来,“国学热”“汉服热”席卷中国年轻群体,各类推广中华传统文化的活动广受青年人追捧。在天津,一个以大学生群体为主的国学兴趣小组正
在每台电脑的右下角,都会有一个喇叭形状的音量图标。我们也可以称这个图标为“扬声器”。当我们看电影的时候,可以通过这个图标
1、“武林至尊,一剑斩龙,号令天下,不敢违逆,不靠天,谁与你争”出自金庸先生小说《倚天屠龙记》。2、103010是武侠大
3月16日,富国中证500指数增强(LOF)A最新单位净值为2 264元,累计净值为2 633元,较前一交易日下跌1 22%。历史数据显示该基金近1个月下跌1 69%
1、这种退票在业内告诉升舱换开,是有条件的,第一,你新票的差价,要大于改期费,第二,你换开的票要乘坐之后才能申请旧票全退
长宁华阳“关爱保护云”启动,试点数据赋能未成年人保护
开局先上超级英雄:感觉如何?这些可是通过直接用陈述性文字直接产生的图片哦!为了实现这种效果,需要先安装一个插件:https: github com ha
1、即使输掉了一切,也不要输掉微笑,不开心的时候别先学着抱怨。2、也不要皱眉,因为你永远不知道谁会爱上你的笑容……。本文
1、考编就是老师编考。2、没有固定的时间。3、当地教育局将根据省市编制不足情况开展相关工作。4、所以每个地区的考试时间都
【热门剧演员原声率鞠婧祎、许凯垫底】不知从何时起,演员自己“说”台词,竟也成为大众热议的话题。以近日热播的《心想事成》《
3月15日,浙江杭州,陈女士称,3月6日入职季小白文化传媒有限公司,工作7天后公司质疑自己工作态度不好,想要对自己调岗降薪,遭拒绝后公司将
1、《微雨宿颐和园听鹂馆晓晴》是清末至民国杨圻创作的一首诗。2、。本文到此分享完毕,希望对大家有所帮助。
3月15日北向资金减持8100 0股大族数控。近5个交易日中,获北向资金减持的有4天,累计净减持3 65万股。近20个交易日中,获北向资金增持的有11天
澳大利亚蜇人树有多“危险”?见到最好绕着走澳大利亚蜇人树是世界上最危险的树之一,其毒性极强,已造成多起伤害和死亡事件。它生长在澳大利
Copyright 2015-2022 南方酒业网 版权所有 备案号:粤ICP备18023326号-21 联系邮箱:855 729 8@qq.com