表定义如下

如果我们需要在表中查询这个树状结构,通过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存储的树形结构,层次结构的更多相关文章

  1. Python查询Mysql时返回字典结构的代码

    Python查询Mysql时返回字典结构的代码 MySQLdb默认查询结果都是返回tuple,输出时候不是很方便,必须按照0,1这样读取,无意中在网上找到简单的修改方法,就是传递一个cursors.D ...

  2. 关于mysql中数据存储复合树形结构,查询时结果按树形结构输出

    1.主要思想:根据已有数据,规则性的造数据 select * FROM(select lId,strName,lId as lParentId,-1 as orderIdx from tbClassi ...

  3. 数据库查询,显示为树形结构(easyui+SSM)

    在实际项目上,有很多地方后台存了一个表,但是在显示查询的时候需要显示为树形结构. 本项目是easyui+SSM框架. 前台程序为: <!DOCTYPE html> <html> ...

  4. 【MySQL疑难杂症】如何将树形结构存储在数据库中(方案一、Adjacency List)

    今天来看看一个比较头疼的问题,如何在数据库中存储树形结构呢? 像mysql这样的关系型数据库,比较适合存储一些类似表格的扁平化数据,但是遇到像树形结构这样有深度的人,就很难驾驭了. 举个栗子:现在有一 ...

  5. Mysql通过Adjacency List(邻接表)存储树形结构

    转载自:https://www.jb51.net/article/130222.htm 以下内容给大家介绍了MYSQL通过Adjacency List (邻接表)来存储树形结构的过程介绍和解决办法,并 ...

  6. MySql/Oracle树形结构查询

    Oracle树形结构递归查询 在Oracle中,对于树形查询可以使用start with ... connect by select * from treeTable start with id='1 ...

  7. 「SQL归纳」树形结构表的存储与查询功能的实现——通过路径方法(非递归)

    一.树形结构例子分析: 以360问答页面为例:http://wenda.so.com/c/ 我们通过观察URL,可以明确该页面的数据以树形结构存储,下面三块模块分别为: ①根节点 ②根节点的第一层子节 ...

  8. MySql树形结构(多级菜单)查询设计方案

    背景 又很久没更新了,很幸运地新冠引发了严重的上呼吸道感染,大家羊过后注意休息和防护 工作中(尤其是传统项目中)经常遇到这种需要,就是树形结构的查询(多级查询),常见的场景有:组织架构(用户部门)查询 ...

  9. 为什么 MySQL 索引要使用 B+树而不是其它树形结构?比如 B 树?

    一个问题? InnoDB一棵B+树可以存放多少行数据?这个问题的简单回答是:约2千万 为什么是这么多呢? 因为这是可以算出来的,要搞清楚这个问题,我们先从InnoDB索引数据结构.数据组织方式说起. ...

  10. 为什么MySQL索引要使用 B+树,而不是其它树形结构?

    作者:李平 https://www.cnblogs.com/leefreeman/p/8315844.html 一个问题? InnoDB一棵B+树可以存放多少行数据?这个问题的简单回答是:约2千万 为 ...

随机推荐

  1. webview2 示例 Samples Selenium

    https://github.com/MicrosoftEdge/WebView2Samples https://learn.microsoft.com/zh-cn/microsoft-edge/we ...

  2. weinre  远程实时调试手机上的Web页面 JAVASCRIPT远程调试

    版权归作者所有,任何形式转载请联系作者.作者:U_U(来自豆瓣)来源:https://www.douban.com/note/289846168/ 调试前端页面我一直使用着神器Chrome开发人员工具 ...

  3. MQ的相关概念

    MQ的相关概念 什么是MQ ​ MQ(message queue),从字面意思上看,本质是个队列,FIFO 先入先出,只不过队列中存放的内容是 message 而已,还是一种跨进程的通信机制,用于上下 ...

  4. itest(爱测试) 开源接口测试,敏捷测试管理平台10.0.0GA 发布

    一:itest work 简介 itest work 开源敏捷测试管理,包含极简的任务管理,测试管理,缺陷管理,测试环境管理,接口测试,接口Mock,还有压测 ,又有丰富的统计分析,8合1工作站.可按 ...

  5. 8个实用的Java Streams API

    分享8个开箱即用的API,方便日常处理集合. 1. 快速过滤空值:Stream.ofNullable 该方法是在 Java 9 中引入的,有助于过滤集合中的所有空值,从而可能使我们避免空指针异常. 在 ...

  6. Qt QMainWindow的使用

    参考视频:黑马科技:https://www.bilibili.com/video/BV1XW411x7NU?p=19 QMainWindow是一个为用户提供主窗口程序的类,包含一个菜单栏(menu b ...

  7. 通过 Canal 将 MySQL 数据实时同步到 Easysearch

    Canal 是阿里巴巴集团提供的一个开源产品,能够通过解析数据库的增量日志,提供增量数据的订阅和消费功能.使用 Canal 模拟成 MySQL 的 Slave,实时接收 MySQL 的增量数据 bin ...

  8. mysql中常用的三种插入数据的语句

    mysql中常用的三种插入数据的语句: insert into表示插入数据,数据库会检查主键(PrimaryKey),如果出现重复会报错: replace into表示插入替换数据,需求表中有Prim ...

  9. work06

    练习题:=============================================================第七题: 1.定义方法 isSXH(int num) 功能:判断数字n ...

  10. 支付宝spi接口设计验签和返回结果加签注意点,支付宝使用JSONObject对象

    支付宝spi接口设计验签和返回结果加签注意点,支付宝使用JSONObject对象 SPI 三方服务接入指南https://opendocs.alipay.com/isv/spiforisv 服务端实现 ...