当前位置: 移动技术网 > IT编程>数据库>Mysql > 教你如何使用MySQL8递归的方法

教你如何使用MySQL8递归的方法

2020年03月09日  | 移动技术网IT编程  | 我要评论
之前写过一篇 mysql通过自定义函数的方式,递归查询树结构,从mysql 8.0 开始终于支持了递归查询的语法 cte 首先了解一下什么是 cte,全名 common t

之前写过一篇 mysql通过自定义函数的方式,递归查询树结构,从mysql 8.0 开始终于支持了递归查询的语法

cte

首先了解一下什么是 cte,全名 common table expressions

with
 cte1 as (select a, b from table1),
 cte2 as (select c, d from table2)
select b, d from cte1 join cte2
where cte1.a = cte2.c;

cte1, cte2 为我们定义的cte,可以在当前查询中引用

可以看出 cte 就是一个临时结果集,和派生表类似,二者的区别这里不细说,可以参考下mysql开发文档:

递归查询

先来看下递归查询的语法

with recursive cte_name as
(
  select ...   -- return initial row set
  union all / union distinct
  select ...   -- return additional row sets
)
select * from cte;
  • 定义一个cte,这个cte 最终的结果集就是我们想要的 ”递归得到的树结构",recursive 代表当前 cte 是递归的
  • 第一个select 为 “初始结果集”
  • 第二个select 为递归部分,利用 "初始结果集/上一次递归返回的结果集" 进行查询得到 “新的结果集”
  • 直到递归部分结果集返回为null,查询结束
  • 最终union all 会将上述步骤中的所有结果集合并(union distinct 会进行去重),再通过 select * from cte; 拿到所有的结果集

递归部分不能包括:

  • 聚合函数例如 sum()
  • group by
  • order by
  • limit
  • distinct

上面的讲解可能有点抽象,通过例子慢慢来理解

with recursive cte (n) as -- 这里定义的n相当于结果集的列名,也可在下面查询中定义
(
 select 1
 union all
 select n + 1 from cte where n < 5
)
select * from cte;


-- result
+------+
| n  |
+------+
|  1 |
|  2 |
|  3 |
|  4 |
|  5 |
+------+

  • 初始结果集为 n =1
  • 这时候看递归部分,第一次执行 cte结果集即是 n =1,条件发现并不满足 n < 5,返回 n + 1
  • 第二次执行递归部分,cte结果集为 n = 2,递归... 直至条件不满足
  • 最后合并结果集

example

最后来看一个树结构的例子

create table `c_tree` (
 `id` int(11) not null auto_increment,
 `cname` varchar(255) collate utf8mb4_unicode_ci default null,
 `parent_id` int(11) default null,
 primary key (`id`)
) engine=innodb auto_increment=13 default charset=utf8mb4 collate=utf8mb4_unicode_ci;
mysql> select * from c_tree;
+----+---------+-----------+
| id | cname  | parent_id |
+----+---------+-----------+
| 1 | 1    |     0 |
| 2 | 2    |     0 |
| 3 | 3    |     0 |
| 4 | 1-1   |     1 |
| 5 | 1-2   |     1 |
| 6 | 2-1   |     2 |
| 7 | 2-2   |     2 |
| 8 | 3-1   |     3 |
| 9 | 3-1-1  |     8 |
| 10 | 3-1-2  |     8 |
| 11 | 3-1-1-1 |     9 |
| 12 | 3-2   |     3 |
+----+---------+-----------+
mysql> 
with recursive tree_cte as
(
  select * from c_tree where parent_id = 3
  union all
  select t.* from c_tree t inner join tree_cte tcte on t.parent_id = tcte.id
)
select * from tree_cte;
+----+---------+-----------+
| id | cname  | parent_id |
+----+---------+-----------+
| 8 | 3-1   |     3 |
| 12 | 3-2   |     3 |
| 9 | 3-1-1  |     8 |
| 10 | 3-1-2  |     8 |
| 11 | 3-1-1-1 |     9 |
+----+---------+-----------+
  • 初始结果集r0 = select * from c_tree where parent_id = 3
  • 递归部分,第一次 r0 与 c_tree inner join 得到 r1
  • r1 再与 c_tree inner join 得到 r2
  • ...
  • 合并所有结果集 r0 + ... + ri

更多信息


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网