教你如何使用MySQL8递归的方法
程序员文章站
2023-11-02 10:52:58
之前写过一篇 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
更多信息
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 使用3dmax画球体模型的方法