Mysql 8+支持递归查询 recursive关键字
背景
递归查询表中下级/上级数据(可指定递归多少层)
本文参照实现Oracle的递归 start with … connect by … prior。
当然,recursive关键字自由度很高,可以自行考虑实现怎样的功能,阶乘等等基于递归都可以。
注意存在递归最大层数1000的限制
ps:关键字没用大写
表中数据
栗子
先说下语法吧,不然可能要瞪眼理解一会。
一.with … as (…)语法 ,当然可以直接跳过不看这里
ps:with as语法视为创建一个临时表(8+版本支持),供其他sql使用,例如:
with
temp1 as (
select 1 as id, '张三' as name
union all
select 2 as id, '李四' as name),
temp2 as (select 1 as id)
select temp1.id, temp1.name
from temp1
join temp2 on temp1.id = temp2.id;
ps:写栗子的时候想着下面这样子实现
with temp as(...),
recursive re_temp() as(...)
select ...from temp...
结果发现会报语法错误,不知是我格式不正确还是目前不支持,欢迎指点。
二.进入正题 with recursive temp(…) as(…)
1.基本实现
-- temp自定义临时表名, (id, name)表示查询哪些字段,按需定义,不必须与下面查询一致,规范起见建议保持一致
with recursive temp(id, `name`) as (
-- 递归所用的基础数据,对照oracle就是start with...
select id, `name`
from source
where id = 1
union all
-- 递归关联查询语句,对照oracle就是connect by ... prior ...
-- 这里就可以根据关联条件来定义是向上还是向下递归咯
select s.id, s.`name`
from source s, temp
where s.pid = temp.id
)
select id, `name` from temp;
查询结果:
以上是基本使用。
参照Oracle,每一层递归记录对应一个level,并可以基于level控制递归层数,这里mysql实现如下:
2.+level实现
with recursive temp(id, `name`, `level`) as (
select id, `name`, 1
from source
where id = 1
union all
select s.id, s.`name`, temp.`level`+1
from source s, temp
where s.pid = temp.id
)
select id, `name`, `level` from temp;
3.+level实现递归层数控制
with recursive temp(id, `name`, `level`) as (
select id, `name`, 1
from source
where id = 1
union all
select s.id, s.`name`, temp.`level`+1
from source s, temp
where s.pid = temp.id
-- 控制递归层数
and `level` < 3
)
select id, `name, `level` from temp;
之前写过基于存储过程和group_concat的mysql递归
基于存储过程和group_concat的mysql比较烦
我之前遇到的坑:
- 子查询调用存储过程需要find_in_set;
- 长度过长需要设置会话级别的group_concat最大长度(group_concat_max_len),强烈不建议直接设置全局变量,有啥想法去找DBA聊聊吧。什么?没有DBA?你就可以为所欲为了?
本文就到这里吧,其他recursive递归编程自行百度。
~~放下手机,关上电脑
~~多做点有意义的事
~~避开疫情,三三两两出去看看风景不香吗
~~带上老婆出去拍个照,白首回望当下的心境不香吗
~~抓起娃娃出去带他长长见识,陪伴孩子点滴成长不香吗
~~读书不要停,学不进去技术就培养下其他感兴趣的书,读书不必有目的。打游戏50年你能得到啥?读书1年你能得到啥?期待你读除了技术外的书,期待你感谢自己。
希望你搜索mysql 递归查询不是上级让你做的~