背景

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

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

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

对于层级固定,层级数少的,一般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. 技术只是工具,多级查询的方式不是固定的,查询方式合理既可,但通常都需要加关系表辅助设计

最新文章

  1. 在虚拟机中安装红旗桌面7.0 Linux操作系统的详细图文教程
  2. 聚合数据董铭彦:小程序开发的兴起将带火API数据交易
  3. MVC3中常用的一些控件及方法
  4. NYOJ 77 开灯问题
  5. [BZOJ2820]YY的GCD
  6. 关于gridview 实现查询功能的方法
  7. (转)phoneGap-Android开发环境搭建
  8. 在Activity中设置new出来的TextView属性
  9. Generating Huge reports in JasperReports
  10. use_virtual_func_without_pointer_left
  11. solr可用于集群的搜索 【转】
  12. Linux read语法及浅析
  13. [SCOI2007]压缩 区间dp
  14. 社团的CTF逆向题WriteUp
  15. Notepad++编译和运行C语言 (GCC)
  16. Linux 安装golang
  17. [HNOI2008]玩具装箱TOY(斜率优化)
  18. TDD学习笔记【六】一Unit Test - Stub, Mock, Fake 简介
  19. JS中几种常见的高阶函数
  20. 什么是ThreadLocal

热门文章

  1. Can not set int field xxx to java.lang.Long 错误
  2. 简单将Springboot项目部署到linux服务器上
  3. html点击a标签弹窗QQ聊天界面
  4. MasaFramework -- 缓存入门与设计
  5. SpringCloud微服务实战——搭建企业级开发框架(四十七):【移动开发】整合uni-app搭建移动端快速开发框架-添加Axios并实现登录功能
  6. vim常用快捷键总结一(光标移动命令)
  7. Optional用法与争议点
  8. C#在Xp系统执行.exe程序的报错怎么查看原因
  9. JUnit 5 单元测试教程
  10. kubernetes_CoreDNS全解析