如何查询MySQL存储的树形结构,层次结构
表定义如下

如果我们需要在表中查询这个树状结构,通过SQL语句,有两种查询方法:
1.通过inner自连接查询,适用于简单的结构
SELECT
*
FROM
course_category AS one
INNER JOIN course_category AS two ON two.parentid = one.id
WHERE
one.parentid = '1'
ORDER BY
one.orderby,
two.orderby
2.通过CTE(Common Table Expression)递归查询:适用于灵活的表结构:需要多层递归
首先举一个递归sql的例子
WITH recursive t1 as ( # with关键字用于定义CTE,,recursive关键字表示这是一个递归CTE
SELECT 1 as n # 递归的基础部分,
union all # 用于将两个select的结果集合并,与union不同的是他不会去重
SELECT n+1 FROM t1 where n<5
)
select * from t1
关于性能:MySQL规定默认递归次数不能超过1000次,并且可以通过设置cte_max_recursion_depth参数来增加递归深度,通过cte_max_recursion_time限制执行时间。
MySQL递归是在存储过程中执行若干次sql语句,java程序在调用方法时会与数据库仅建立一次链接来执行递归操作。因此控制好递归次数不会影响性能
什么是存储过程:一组为了完成特定功能的SQL语句集合
# 从根节点向下递归
WITH recursive t1 as (
SELECT * FROM course_category WHERE id='1' #取得了树根
union all
SELECT course_category.* FROM course_category INNER JOIN t1 on t1.id=course_category.parentid
)
SELECT * FROM t1 ORDER BY id
# 从叶子节点向上递归
WITH recursive t1 as (
SELECT * FROM course_category WHERE id='1-1-1' #取得了树根
union all
SELECT course_category.* FROM course_category INNER JOIN t1 on t1.parentid=course_category.id
)
SELECT * FROM t1 ORDER BY id
如何在java中使用:
首先除了po以外,还需要一个dto,dto需要extends po,同时内包含一个List<dto>childTreeNodes属性
service层方法:获取当前节点的所有子节点后,通过遍历所有节点,依次构造树形关系
public List<CourseCategoryTreeDto> queryTreeNodes(String id) {
List<CourseCategoryTreeDto> courseCategoryTreeDtoList = mapper.selectTreeNodes(id);
// 为了方便获取结点,封装到map中
Map<String, CourseCategoryTreeDto> map = courseCategoryTreeDtoList
.stream()
.filter(item -> !id.equals(item.getId()))
.collect(Collectors.toMap(key -> key.getId(), value -> value, (key1, key2) -> key2));
List<CourseCategoryTreeDto> list = new ArrayList<>();
// 遍历所有节点,如果是当前节点的下一级节点,加入到list中;如果不是,则找到他的父节点并在list中成为父节点的子节点
courseCategoryTreeDtoList
.stream()
.filter(item -> !id.equals(item.getId()))
.forEach(node -> {
// 如果是当前节点的下一级节点
if (node.getParentid().equals(id)) {
list.add(node);
}
// 找到当前节点相应的父节点
CourseCategoryTreeDto courseCategoryTreeParent = map.get(node.getParentid());
// 父节点可能有不存在的情况,比如根节点已经在上面过滤掉了,因此一级子节点的父节点是空的
if (courseCategoryTreeParent != null) {
// 如果父节点属性为null,需要new一下集合
if (courseCategoryTreeParent.getChildrenTreeNodes() == null) {
courseCategoryTreeParent.setChildrenTreeNodes(new ArrayList<>());
}
// 将当前节点加入到父节点的子节点中
courseCategoryTreeParent.getChildrenTreeNodes().add(node);
}
});
return list;
}
如何查询MySQL存储的树形结构,层次结构的更多相关文章
- Python查询Mysql时返回字典结构的代码
Python查询Mysql时返回字典结构的代码 MySQLdb默认查询结果都是返回tuple,输出时候不是很方便,必须按照0,1这样读取,无意中在网上找到简单的修改方法,就是传递一个cursors.D ...
- 关于mysql中数据存储复合树形结构,查询时结果按树形结构输出
1.主要思想:根据已有数据,规则性的造数据 select * FROM(select lId,strName,lId as lParentId,-1 as orderIdx from tbClassi ...
- 数据库查询,显示为树形结构(easyui+SSM)
在实际项目上,有很多地方后台存了一个表,但是在显示查询的时候需要显示为树形结构. 本项目是easyui+SSM框架. 前台程序为: <!DOCTYPE html> <html> ...
- 【MySQL疑难杂症】如何将树形结构存储在数据库中(方案一、Adjacency List)
今天来看看一个比较头疼的问题,如何在数据库中存储树形结构呢? 像mysql这样的关系型数据库,比较适合存储一些类似表格的扁平化数据,但是遇到像树形结构这样有深度的人,就很难驾驭了. 举个栗子:现在有一 ...
- Mysql通过Adjacency List(邻接表)存储树形结构
转载自:https://www.jb51.net/article/130222.htm 以下内容给大家介绍了MYSQL通过Adjacency List (邻接表)来存储树形结构的过程介绍和解决办法,并 ...
- MySql/Oracle树形结构查询
Oracle树形结构递归查询 在Oracle中,对于树形查询可以使用start with ... connect by select * from treeTable start with id='1 ...
- 「SQL归纳」树形结构表的存储与查询功能的实现——通过路径方法(非递归)
一.树形结构例子分析: 以360问答页面为例:http://wenda.so.com/c/ 我们通过观察URL,可以明确该页面的数据以树形结构存储,下面三块模块分别为: ①根节点 ②根节点的第一层子节 ...
- MySql树形结构(多级菜单)查询设计方案
背景 又很久没更新了,很幸运地新冠引发了严重的上呼吸道感染,大家羊过后注意休息和防护 工作中(尤其是传统项目中)经常遇到这种需要,就是树形结构的查询(多级查询),常见的场景有:组织架构(用户部门)查询 ...
- 为什么 MySQL 索引要使用 B+树而不是其它树形结构?比如 B 树?
一个问题? InnoDB一棵B+树可以存放多少行数据?这个问题的简单回答是:约2千万 为什么是这么多呢? 因为这是可以算出来的,要搞清楚这个问题,我们先从InnoDB索引数据结构.数据组织方式说起. ...
- 为什么MySQL索引要使用 B+树,而不是其它树形结构?
作者:李平 https://www.cnblogs.com/leefreeman/p/8315844.html 一个问题? InnoDB一棵B+树可以存放多少行数据?这个问题的简单回答是:约2千万 为 ...
随机推荐
- win10离线安装.net3.5失败的解决方案
简介: 问题:有时候需要离线安装.net3.5环境,网上的教程一般都是通过NetFx3.cab进行离线安装,但有时候会出现离线安装失败,比如: by~MaQaQ 2024-06-04 分析: 1.先关 ...
- Linux 提权-Cron Jobs
本文通过 Google 翻译 Cron Jobs – Linux Privilege Escalation - Juggernaut-Sec 这篇文章所产生,本人仅是对机器翻译中部分表达别扭的字词进行 ...
- react移动端组件antd-mobile
使用react移动端组件antd-mobile完成底部导航功能实现. 官网:https://mobile.ant.design/docs/react/introduce-cn antd-mobile ...
- vue过滤器 - filters
在数据被渲染之前,可以对其进行进一步处理,比如将字符截取或者将小写统一转换为大写等等,过滤器本身就是一个方法. 过滤器可以定义全局或局部 # 全局 // 回调函数中的参数1永久是绑定的数据 Vue.f ...
- linux系统下,redis如何设置密码
1.命令方式 首先查看下密码是否存在,发现并未设置为空. -bash-4.2# cd /usr/local/redis-6.2.6/src -bash-4.2# ./redis-cli 127.0.0 ...
- SRE 排障利器,接口请求超时试试 httpstat
夜莺资深用户群有人推荐的一个工具,看了一下真挺好的,也推荐给大家. 需求场景 A 服务调用 B 服务的 HTTP 接口,发现 B 服务返回超时,不确定是网络的问题还是 B 服务的问题,需要排查. 工具 ...
- springboot项目添加logback日志
1.application.yml 配置日志文件路径: logging: config: classpath:logback.xml file: /usr/local/log/projectName/ ...
- SoftReference 到底在什么时候被回收 ? 如何量化内存不足 ?
本文基于 OpenJDK17 进行讨论,垃圾回收器为 ZGC. 提示: 为了方便大家索引,特将在上篇文章 <以 ZGC 为例,谈一谈 JVM 是如何实现 Reference 语义的> 中讨 ...
- IS-IS总结
IS-IS 管理距离115 ISIS是链路状态协议 封装在数据链路层,所以没有协议号 使用SPF算法计算最短路径 没有骨干区的概念 使用IIH(ISIS ...
- 使用Redis+SpringBoot实现定时任务测试
Redis实现定时任务是基于对RedisKey值的监控 具体代码实现: 代码GitHub地址:https://github.com/Tom-shushu/Project 建一个SpringBoot项目 ...