MySQL 8.0新特性--CTE Recurive(二)
发表于:2025-02-01 作者:千家信息网编辑
千家信息网最后更新 2025年02月01日,上一篇介绍了CTE的基本用法,参考MySQL 8.0新特性--CTE(一),本篇再来介绍一下CTE Recurive递归。1、什么是CTE Recurive?A recursive common ta
千家信息网最后更新 2025年02月01日MySQL 8.0新特性--CTE Recurive(二)
上一篇介绍了CTE的基本用法,参考MySQL 8.0新特性--CTE(一),本篇再来介绍一下CTE Recurive递归。
1、什么是CTE Recurive?
A recursive common table expression is one having a subquery that refers to its own name.
个人理解:在CTE定义中调用先前定义的CTE,并且在查询的时候,循环调用CTE.
例如:
mysql> WITH RECURSIVE cte (n) AS -> ( -> SELECT 1 -> UNION ALL -> SELECT n + 1 FROM cte WHERE n < 5 -> ) -> SELECT * FROM cte;+------+| n |+------+| 1 || 2 || 3 || 4 || 5 |+------+5 rows in set (0.00 sec)
注意字符串长度:
mysql> WITH RECURSIVE cte AS -> ( -> SELECT 1 AS n, 'abc' AS str -> UNION ALL -> SELECT n + 1, CONCAT(str, str) FROM cte WHERE n < 3 -> ) -> SELECT * FROM cte;ERROR 1406 (22001): Data too long for column 'str' at row 1mysql> WITH RECURSIVE cte AS -> ( -> SELECT 1 AS n, CAST('abc' AS CHAR(20)) AS str -> UNION ALL -> SELECT n + 1, CONCAT(str, str) FROM cte WHERE n < 3 -> ) -> SELECT * FROM cte;+------+--------------+| n | str |+------+--------------+| 1 | abc || 2 | abcabc || 3 | abcabcabcabc |+------+--------------+3 rows in set (0.00 sec)
2、CTE Recurive递归中的参数限制
(1)cte_max_recursion_depth 控制调用递归的次数,默认1000次
例如:
当调用cte为1001次的时候,查询报错mysql> WITH RECURSIVE cte (n) AS -> ( -> SELECT 1 -> UNION ALL -> SELECT n + 1 FROM cte where n<1001 -> ) -> SELECT * FROM cte;ERROR 3636 (HY000): Recursive query aborted after 1001 iterations. Try increasing @@cte_max_recursion_depth to a larger value.
(2)max_execution_time 强制会话超时时间,默认0,表示没有开启此功能,单位ms.
例如:
把参数设置为5s,执行超时并报错:mysql> SET max_execution_time = 5000; #5sQuery OK, 0 rows affected (0.00 sec)mysql> select s.* from salaries s where s.emp_no in (select emp_no from employees e where e.first_name='Georgi' union all select emp_no from employees e where e.hire_date='1992-12-18');ERROR 3024 (HY000): Query execution was interrupted, maximum statement execution time exceeded把参数设置为50s,执行成功:SET max_execution_time = 50000;mysql> select s.* from salaries s where s.emp_no in (select emp_no from employees e where e.first_name='Georgi' union all select emp_no from employees e where e.hire_date='1992-12-18');2718 rows in set (21.70 sec)
3、CTE Recurive递归的几个经典示例
(1)斐波纳契数列问题
mysql> WITH RECURSIVE fibonacci (n, fib_n, next_fib_n) AS -> ( -> SELECT 1, 0, 1 -> UNION ALL -> SELECT n + 1, next_fib_n, fib_n + next_fib_n -> FROM fibonacci WHERE n < 10 -> ) -> SELECT * FROM fibonacci;+------+-------+------------+| n | fib_n | next_fib_n |+------+-------+------------+| 1 | 0 | 1 || 2 | 1 | 1 || 3 | 1 | 2 || 4 | 2 | 3 || 5 | 3 | 5 || 6 | 5 | 8 || 7 | 8 | 13 || 8 | 13 | 21 || 9 | 21 | 34 || 10 | 34 | 55 |+------+-------+------------+10 rows in set (0.00 sec)
(2)连续日期问题
mysql> WITH RECURSIVE dates (date) AS( SELECT MIN(date) FROM sales UNION ALL SELECT date + INTERVAL 1 DAY FROM dates WHERE date + INTERVAL 1 DAY <= (SELECT MAX(date) FROM sales))SELECT * FROM dates;+------------+| date |+------------+| 2017-01-03 || 2017-01-04 || 2017-01-05 || 2017-01-06 || 2017-01-07 || 2017-01-08 || 2017-01-09 || 2017-01-10 |+------------+mysql> WITH RECURSIVE dates (date) AS( SELECT MIN(date) FROM sales UNION ALL SELECT date + INTERVAL 1 DAY FROM dates WHERE date + INTERVAL 1 DAY <= (SELECT MAX(date) FROM sales))SELECT dates.date, COALESCE(SUM(price), 0) AS sum_priceFROM dates LEFT JOIN sales ON dates.date = sales.dateGROUP BY dates.dateORDER BY dates.date;+------------+-----------+| date | sum_price |+------------+-----------+| 2017-01-03 | 300.00 || 2017-01-04 | 0.00 || 2017-01-05 | 0.00 || 2017-01-06 | 50.00 || 2017-01-07 | 0.00 || 2017-01-08 | 180.00 || 2017-01-09 | 0.00 || 2017-01-10 | 5.00 |+------------+-----------+
(3)分层数据遍历问题
mysql> CREATE TABLE employees ( -> id INT PRIMARY KEY NOT NULL, -> name VARCHAR(100) NOT NULL, -> manager_id INT NULL, -> INDEX (manager_id), -> FOREIGN KEY (manager_id) REFERENCES EMPLOYEES (id) -> );Query OK, 0 rows affected (0.44 sec)mysql> INSERT INTO employees VALUES -> (333, "Yasmina", NULL), # Yasmina is the CEO (manager_id is NULL) -> (198, "John", 333), # John has ID 198 and reports to 333 (Yasmina) -> (692, "Tarek", 333), -> (29, "Pedro", 198), -> (4610, "Sarah", 29), -> (72, "Pierre", 29), -> (123, "Adil", 692);Query OK, 7 rows affected (0.09 sec)Records: 7 Duplicates: 0 Warnings: 0mysql> SELECT * FROM employees ORDER BY id;+------+---------+------------+| id | name | manager_id |+------+---------+------------+| 29 | Pedro | 198 || 72 | Pierre | 29 || 123 | Adil | 692 || 198 | John | 333 || 333 | Yasmina | NULL || 692 | Tarek | 333 || 4610 | Sarah | 29 |+------+---------+------------+7 rows in set (0.00 sec)mysql> WITH RECURSIVE employee_paths (id, name, path) AS -> ( -> SELECT id, name, CAST(id AS CHAR(200)) -> FROM employees -> WHERE manager_id IS NULL -> UNION ALL -> SELECT e.id, e.name, CONCAT(ep.path, ',', e.id) -> FROM employee_paths AS ep JOIN employees AS e -> ON ep.id = e.manager_id -> ) -> SELECT * FROM employee_paths ORDER BY path;+------+---------+-----------------+| id | name | path |+------+---------+-----------------+| 333 | Yasmina | 333 || 198 | John | 333,198 || 29 | Pedro | 333,198,29 || 4610 | Sarah | 333,198,29,4610 || 72 | Pierre | 333,198,29,72 || 692 | Tarek | 333,692 || 123 | Adil | 333,692,123 |+------+---------+-----------------+7 rows in set (0.00 sec)
参考链接
13.2.13 WITH Syntax (Common Table Expressions)
递归
参数
问题
时候
参考
查询
特性
成功
个人
功能
单位
字符
字符串
数列
数据
日期
时间
次数
示例
经典
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
西城区网络营销软件开发程序
原神深境数据库
l4d2怎么选服务器
win7本地服务器在哪
软件开发过程中有哪些版本
慈溪软件开发项目
电教馆网络安全工作职责
r620服务器设置硬盘启动
管家婆无法连接到服务器
儿童教育应用软件开发
哪些方式保护个人网络安全
三万的服务器机柜可以防辐射吗
第三方网络安全等级评测单位
服务器cpu波动正常吗
郑州软件开发驻场报价
伊金霍洛旗网络安全宣传
pubg手游该选哪个服务器
福州众点网络技术开发有限公司
做时间服务器的关键是什么
网络安全设计权威指南
股票 投资 合作 软件开发
自定义数据库域名
元数建模如何连接数据库
网络安全法我来普法
服务器网卡灯不亮
互联网企业网络安全应对措施
南通服务器机柜定做
农村网络安全距离
魔灵召唤都有几个服务器
西宁软件开发应用范围