Mysql树形表的2种查询解决方案(递归与自连接)

 更新时间:2023年11月25日 08:35:04   作者:懒羊羊.java  
MySQL作为一个关系型数据库,存储着许多的数据信息,在实际应用中经常会遇到需要存储树形结构数据的情境,例如部门结构、商品分类等,这篇文章主要给大家介绍了关于Mysql树形表的2种查询解决方案,分别是递归与自连接,需要的朋友可以参考下

你有没有遇到过这样一种情况:

一张表就实现了一对多的关系,并且表中每一行数据都存在“爷爷-父亲-儿子-…”的联系,这也就是所谓的树形结构

对于这样的表很显然想要通过查询来实现价值绝对是不能只靠select * from table 来实现的,下面提供两种解决方案:

1.自连接

inner join 关键可以实现多种分类的查询,其实SQL很简单

SELECT
	one.id one_id,
	one.label one_label,
	two.id two_id,
	two.label two_label
FROM
	course_category one
	INNER JOIN course_category two ON two.parentid=one.id
	INNER JOIN course_category three ON three.parentid=two.id
	WHERE one.id='1' AND one.is_show='1' AND two.is_show='1'
	ORDER BY one.orderby,two.orderby

也是规规矩矩的就查出一整棵树

这种查询的原则就是通过parentId去实现,“爷爷找爸爸,爸爸找儿子,儿子找孙子”,下面来逐帧慢放:

1.one

2.one,two

3.one,two,three

可以看到,只有在树的层级确定的情况下我才能选择性的去自连接子表,某种意义上来讲这种方法存在弊端,我要是insert进去层级更低的新子节点那我的sql就得改变,从而就造成了一个“动一发而牵全身”的硬编码问题,实在是不够稳妥!

2.递归!

向上递归

首先声明,如果mysql的版本低于8是不支持递归查询的函数的!

下面来看一下如何用递归优雅的实现,从树根查到树顶:

先来看一个简单的Demo

	with RECURSIVE t1 AS(
		SELECT 1 AS n
		union all
		SELECT n+1 FROM t1 WHERE n<5
	)
	SELECT * from t1

该怎么理解这每一步呢?
 

WITH RECURSIVE t1 AS:

这是递归查询的开始,创建了一个名为t1的递归表。

SELECT 1 AS n:

在t1表中,插入了一个初始行,值为1,命名为n。

UNION ALL:

使用UNION ALL运算符将初始行和递归查询结果合并,形成递归步骤。这也就是下次递归的起点表

SELECT n+1 FROM t1 WHERE n<5:

递归部分的查询,从t1表中选择n加1的结果,当n小于5时进行递归。

SELECT * FROM t1:

最终查询,返回t1表的所有行。

其实在使用递归的过程只需要注意要去避免死龟就好!

如何去查开头的那张树形表呢?这样就好:

with recursive temp as (
select * from  course_category p where  id= '1'
 union all
select t.* from course_category t inner join temp on temp.id = t.parentid
)
select *  from temp order by temp.id, temp.orderby

下面我们逐帧分析:

其实关键的地方就在于第三步,在树根的基础上去找叶子:

神之一手:
select t.* from course_category t inner join temp on temp.id = t.parentid
这就是递归相较于第一种方式可以无视层级inner jion的关键,因为这个动作已经被递归自动完成了,递归巧妙地一点就在这里!

向下递归

基于向上递归父找子的思想,向下递归则是子找父,即在叶子基础上union all之后去找根

子的parentId=父的id

with recursive temp as (
select * from  course_category p where  id= '1-1-1'
 union all
select t.* from course_category t inner join temp on temp.parentid = t.id  
//temp表是下次递归的基础
)
select *  from temp order by temp.id, temp.orderby

值得注意的是Mysql为了避免无限递归递归次数为1000次,也可以人为来设置cte_max_recursion_depth和max_execution_time来自定义递归深度和执行时间

使用递归的好处无需言语,一次io连接就搞定了全部

总结

到此这篇关于Mysql树形表的2种查询解决方案的文章就介绍到这了,更多相关Mysql树形表查询内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • mysql获取随机数据的方法

    mysql获取随机数据的方法

    在mysql中获取随机数据方法很简单只要使用order by rand()即可了,但是如果你是百万级数据量,使用order by rand()获取随机数据你会等死去,下面我来介绍具体的解决办法
    2013-11-11
  • MySQL varchar(n)能存储几个汉字

    MySQL varchar(n)能存储几个汉字

    这篇文章主要介绍了MySQL varchar(n)能存储几个汉字,MySQL中varchar(n)表示n个字符,无论汉字和英文,Mysql都能存入n个字符,仅是实际字节长度有所区别,本文给大家介绍的非常详细,需要的朋友可以参考下
    2023-05-05
  • 详解MySQL执行原理、逻辑分层、更改数据库处理引擎

    详解MySQL执行原理、逻辑分层、更改数据库处理引擎

    在本文里我们给大家总结了关于MySQL执行原理、逻辑分层、更改数据库处理引擎的相关知识点,需要的读者们一起学习下。
    2019-02-02
  • MySQL数据库常见字段类型长度汇总大全

    MySQL数据库常见字段类型长度汇总大全

    这篇文章主要给大家介绍了关于MySQL数据库常见字段类型长度汇总大全的相关资料,需要的朋友可以参考下
    2024-05-05
  • MySQL批量插入唯一索引冲突的几种避免办法

    MySQL批量插入唯一索引冲突的几种避免办法

    我们在进行大批量的数据插入时,遇到唯一索引冲突是经常的事,本文主要介绍了MySQL批量插入唯一索引冲突的几种避免办法,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • Mysql利用group by分组排序

    Mysql利用group by分组排序

    这篇文章主要为大家详细介绍了Mysql利用group by分组排序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • 几种MySQL中的联接查询操作方法总结

    几种MySQL中的联接查询操作方法总结

    这篇文章主要介绍了几种MySQL中的联接查询操作方法总结,文中包括一些代码举例讲解,需要的朋友可以参考下
    2015-04-04
  • mysql免安装版配置教程

    mysql免安装版配置教程

    这篇文章主要为大家详细介绍了mysql免安装版配置教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-01-01
  • 如何批量生成MySQL不重复手机号大表实例代码

    如何批量生成MySQL不重复手机号大表实例代码

    这篇文章主要给大家介绍了关于如何批量生成MySQL不重复手机号大表的相关资料,,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • MySQL 索引优化案例

    MySQL 索引优化案例

    这篇文章主要介绍了MySQL 索引优化案例,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感兴趣的小伙伴可以参考一下,希望对你的学习有所帮助
    2022-08-08

最新评论