背景

又很久没更新了,很幸运地新冠引发了严重的上呼吸道感染,大家羊过后注意休息和防护

工作中(尤其是传统项目中)经常遇到这种需要,就是树形结构的查询(多级查询),常见的场景有:组织架构(用户部门)查询 和 多级菜单查询

比如,菜单分为三级,一级菜单、二级菜单、三级菜单,要求用户按树形结构把各级菜单查询出来。如下图所示

对于层级固定,层级数少的,一般3级,需求实现很简单,先查询最小子级,再依次查询上级,最后再组装返回给前端就是了。

那么问题来了,如果层级数很大,10级,或者干脆层级不确定,有的3级,有的5级,有的8级,与之前的层级固定,层级数相比,显然问题更复杂了,我们来看看这种怎么处理

三级查询(层级固定,层级数少)

这种情况,我们只需要一张表,就叫它树形表吧:

CREATE TABLE tree (
id int not null auto_increment,
name varchar(50) not null comment '名称',
parent_id int not null default 0 comment '父级id',
level int not null default 1 comment '层级,从1开始',
created datetime,
modified datetime
);

三级查询过程:查询出三级tree, 根据三级tree的 parent_id 查询出二级tree, 同样的方式再去查询出一级tree, 后端组装成树状数据,返回给前端。

多级查询(层级不固定/层级很深)

这种情况,我们首先想到的就是子查询或者联表查询,但是肯本不能在实际开发中使用,原因大家都知道:

  1. sql语句复杂,容易出错
  2. 性能问题,可能会被领导干

所以最好的方式就是,加一张表 tree_depth,来维护层级深度关系。

CREATE TABLE tree_depth (
id int not null auto_increment,
root_id int not null default 0 comment '根节点(祖先节点)id',
tree_id int not null default 0 comment '当前节点id',
depth int not null default 0 comment '深度(当前节点 tree_id 到 根节点 root_id 的深度)',
created datetime
);

表中 depth 字段表示的是: 当前节点 tree_id 到 根节点 root_id 的深度,不是当前节点所在整个分支的深度,所有节点相对于自身的深度都是0

有了 tree_depth 表后,查询一个N级节点的组织数据就方便了:

遍历整个树:

直接查 tree 中所有 level = 1 的节点,在出去这些节点的 id 根据 parent_id 去查下级节点, 查询完所有的节点,就可以组装成一个完整的树状图返回给前端

节点搜索(查找出这个节点所在的整个分支)

  1. 从 tree 表查询出节点 treeN

    select * from tree where id = N
  2. 根据 treeN 的 id 值,到 tree_depth 表查询出它的 根节点id:

    select root_id from tree_depth where tree_id = #{treeId}
  3. 根据 root_id 查询 tree_depth 的 所有当前节点分支数据

    select * from tree_depth where root_id = #{rootId}
  4. 从查询出 tree_depth 表数据中取出所有当前节点 tree_id

    select * from tree where id in (?,?,?)
  5. 组装所在分支树状结构

总结

  1. 多级查询、三级查询本质就是树形结构的遍历,推荐使用多级查询的方式,相比三级查询多级查询的方式抓住了树形结构遍历的本质,方便扩展和维护。
  2. 技术只是工具,多级查询的方式不是固定的,查询方式合理既可,但通常都需要加关系表辅助设计

MySql树形结构(多级菜单)查询设计方案的更多相关文章

  1. MySQL 树形结构 根据指定节点 获取其所在全路径节点序列

    背景说明 需求:MySQL树形结构, 根据指定的节点,获取其所在全路径节点序列. 问题分析 1.可以使用类似Java这种面向对象的语言,对节点集合进行逻辑处理,获取全路径节点序列. 2.直接自定义My ...

  2. MySQL 树形结构 根据指定节点 获取其所有父节点序列

    背景说明 需求:MySQL树形结构, 根据指定的节点,获取其所有父节点序列. 问题分析 1.可以使用类似Java这种面向对象的语言,对节点集合进行逻辑处理,获取父节点. 2.直接自定义MySQL函数  ...

  3. MySQL 树形结构 根据指定节点 获取其下属的所有子节点(包含路径上的枝干节点和叶子节点)

    背景说明 需求:MySQL树形结构, 根据指定的节点,获取其下属的所有子节点(包含路径上的枝干节点和叶子节点) 枝干节点:如果一个节点下还有子节点,则为枝干节点. 叶子节点:如果一个节点下不再有子节点 ...

  4. MySQL 树形结构 根据指定节点 获取其所有叶子节点

    背景说明 需求:MySQL树形结构, 根据指定的节点,获取其下属的所有叶子节点. 叶子节点:如果一个节点下不再有子节点,则为叶子节点. 问题分析 1.可以使用类似Java这种面向对象的语言,对节点集合 ...

  5. Mybatis实现多级菜单查询

    写在前面 最近实现一个小需求,前端需要菜单的信息,需要向后端发起获取菜单的请求,菜单又是一个多级菜单,后端我用的mybatis进行数据库查询,实现的方法我这里想到有两种,欢迎大家补充. 1. 在Men ...

  6. YbSoftwareFactory 代码生成插件【十八】:树形结构下的查询排序的数据库设计

    树形结构的排序在中国特色下十分普遍也非常重要,例如常说的五大班子,党委>人大>政府>政协>纪委,每个班子下还有部门,岗位,人员,最终排列的顺序通常需要按权力大小.重要性等进行排 ...

  7. vue+element树形结构右键菜单

    环境:vue-admin-template   vue 2.6.10 element-ui 2.7.0 1.自定义组件,文件位置:src/components/mentContext <temp ...

  8. MySQL树形结构的数据库表设计和查询

    1.邻接表(Adjacency List) 实例:现在有一个要存储一下公司的人员结构,大致层次结构如下: 那么怎么存储这个结构?并且要获取以下信息: 1.查询小天的直接上司. 2.查询老宋管理下的直属 ...

  9. mysql树形结构递归查询

    之前一直用的是Oracle,对于树形查询可以使用start with ... connect by ' connect by id = prior parent_id; 没错,这是Oracle所支持的 ...

  10. oracle 多级菜单查询 。start with connect by prior

    select * from S_dept where CODE in(select sd.code from s_dept sd start with sd.code='GDKB' connect b ...

随机推荐

  1. 个人数据保全计划:(1) NAS开箱

    前言 从几年前第一个硬盘故障导致参赛的文件丢失之后,我就开始意识到数据安全的重要性,开始用各种云盘做备份,当时还不是百度云一家独大,我们也都没意识到网盘备份是极其不靠谱的行为,直到因为某些不可抗力因素 ...

  2. mybatis-自定义映射resultMap

    自定义映射resultMap resultMap处理字段和属性的映射关系 resultMap:设置自定义映射 属性: id:表示自定义映射的唯一标识,不能重复 type:查询的数据要映射的实体类的类型 ...

  3. RK3568开发笔记(五):在虚拟机上使用SDK编译制作uboot、kernel和ubuntu镜像

    前言   buildroot虽然灵活,但是基于实际情况,本身是侧重驱动和应用定制开发的只定制一次文件系统投入有点多,还不如直接ubunt自己交叉编译依赖库,做一些库的移植裁剪.  于是本篇就使用ubu ...

  4. JAVA-注解之 TODO、FIXME、XXX

    TODO.FIXME.XXX    //TODO : 表示待实现的功能    //FIXME: 代码存在Bug,不能Run或运行结果不正确,需要修复    //XXX  : 勉强可以工作,但是实现的方 ...

  5. JavaScript 实现地图搜索功能

    需求:输入框输入地址点击查询,查询结果在地图定位到查询位置,显示查询位置的经纬度 <html xmlns="http://www.w3.org/1999/xhtml"> ...

  6. 2022-11-05 Acwing每日一题

    本系列所有题目均为Acwing课的内容,发表博客既是为了学习总结,加深自己的印象,同时也是为了以后回过头来看时,不会感叹虚度光阴罢了,因此如果出现错误,欢迎大家能够指出错误,我会认真改正的.同时也希望 ...

  7. hashcat 命令

    hashcat --force --stdout -a 6 tmp.txt ?d?d?d?d?d?d?d > result.txt tips:将tmp.txt字典中的内容与7位随机掩码字符组合, ...

  8. YeserCMS

    这道题直接让我们查网站根目录的flag,我首先想到的是一句话木马,但是奈何找不到上传的接口啊,只好作罢, 在下载发现有个cmseasy的标识,明显是要提示我们这里是easycms,百度easycms的 ...

  9. 线性时间选择(含平均情况O(n)和最坏情况O(n)算法)

    前言 本篇文章我将介绍 期望为线性时间 的选择算法和 最坏情况为线性时间 的选择算法,即分别为 平均情况下时间复杂度为O(n) 和 最坏情况下时间复杂度为O(n) 的线性时间选择.以下包含了我自己的全 ...

  10. day15 Socket网络编程 & 反射

    day15 知识点浅记一下 ping 使用来icmp来检查网络是否连通,并没有记录路径.  tracert 使用icmp包记录并确定数据包访问目标所经过的路由,因此可以依据此命令判断故障发生的位置 n ...