MySQL 递归查询
本文最后更新于:2020年12月30日 凌晨
场景
最近需要将根据父级分类查询出所有的自己分类,所以却是需要使用 MySQL 实现递归查询的功能。
对于以下数据表(此处简化了)
id | parentId | name |
---|---|---|
1 | 0 | 数学 |
2 | 1 | 高等数学 |
3 | 1 | 线性代数 |
4 | 0 | 英语 |
5 | 4 | 即时翻译 |
6 | 4 | 口语阅读 |
7 | 0 | 物理 |
8 | 7 | 高能物理 |
9 | 8 | 无限能量 |
10 | 9 | 迪克拉之海 |
SQL 结构/数据
1 |
|
吾辈只有一个 id,想要查询出所有的子级
解决
这个问题在网络上流传着各种各样的解决方案
- 使用额外的字段存储节点全路径
- 在应用层递归查询完成
- 使用 Mybatis collection 标签
- 使用存储过程
- 使用 SQL 视图
- 使用单条 SQL 实现
吾辈目前只尝试了其中三种
使用额外的字段存储节点全路径
有人提出使用一个额外的字段记录当前节点的全路径,每一级使用 ,
进行分割,所以吾辈的数据表变成了下面这样
id | parentId | name | path |
---|---|---|---|
1 | 0 | 数学 | 0,1 |
2 | 1 | 高等数学 | 0,1,2 |
3 | 1 | 线性代数 | 0,1,3 |
4 | 0 | 英语 | 0,4 |
5 | 4 | 即时翻译 | 0,4,5 |
6 | 4 | 口语阅读 | 0,4,6 |
7 | 0 | 物理 | 0,7 |
8 | 7 | 高能物理 | 0,7,8 |
9 | 8 | 无限能量 | 0,7,8,9 |
10 | 9 | 迪克拉之海 | 0,7,8,9,10 |
SQL 结构/数据
1 |
|
现在,我们可以很简单的查询了子级信息了
1 |
|
这里使用正则是为了避免出现部分重复的情况,例如
1
和10
,直接使用like
的话可能会出现错误查询额外的数据。
在应用层递归查询完成
在不修改数据表结构的情况下有什么方法能递归查询么?答案是可以的!我们可以在程序中递归查询数据库,虽然效率上会低点,但对于不能修改的数据库而言还是相当有用的。
Domain 实体
1 |
|
Service 及其实现
1 |
|
Dao/Mapper.xml
1 |
|
1 |
|
调用的时候只要传入一个根节点 id 就可以查找到所有节点及其所有子节点了
使用 Mybatis collection 标签
如果你使用的 ORM 是 Mybatis,那么也可以使用 Mybatis collection 标签实现递归查询的功能。
- Mybatis
collection
标签可以查询一个集合为字段赋值 - 那么我们可以使用
select
指向查询子分类本身 - 查询的参数
cloumn
设置为查询出来每一个对象的id
字段 - 更改查询子分类的返回值为
resultMap="RecursiveMap"
1 |
|
1 |
|
那么,关于 MySQL 递归查询暂且到此为止了。如果吾辈找到了更好的方法,也会继续更新这篇文章的!
MySQL 递归查询
https://blog.rxliuli.com/p/040c6e4f06dc481f9ea294bbc6f6c53a/