为什么需要这玩意?
Q: 那递归查询相比一般的查询有什么不同呢?
A: 可以查树形结构(自引用),比如一部门中还有一个子部门,如果要查这个部门中所有的部门,传统查询比较难搞。
要MySQL 8.0 +
先上语法:
WITH RECURSIVE cte_name AS
(
SELECT ... -- return initial row set
UNION ALL / UNION DISTINCT
SELECT ... -- return additional row sets
)
SELECT * FROM cte;
递归采用CTE(Common Table Expressions,With XXX 就是CTE)实现,再详细地解释下:
组成部分解释:
WITH RECURSIVE
:标识这是一个递归的Common Table Expression。
cte_name
:为递归查询定义一个临时的名称,用于在后续查询中引用。
(column_list)
:列出在递归过程中需要的列名。
初始化部分(非递归基) :
SELECT column_list
: 选择开始递归时的基本数据,这些通常是层级结构的顶层节点。FROM table
: 指定数据来源表。WHERE initial_conditions
: 设置初始条件,筛选出递归起点的数据。
UNION ALL
:将初始化部分的结果与递归部分的结果合并。
递归部分(递归步骤) :
SELECT column_list
: 选择在递归过程中需要的列,可能包括从CTE自身引用的列。FROM cte_name
: 引用前面定义的CTE名称,表示递归地基于之前计算出的结果继续查询。JOIN table ON recursion_conditions
: 使用JOIN操作将CTE与原始表或其他相关表连接起来,根据递归条件确定下一层级的数据。
最后的SELECT * FROM cte_name
:从构建好的递归CTE中选择所有数据作为最终查询结果。
举个例子
上图是departments表,能看出,parent_department_id就是一个自引用字段,引的是ID。
我们的SQL语句如下:
WITH RECURSIVE departments_list as
(
SELECT departments.id,departments.department_name,departments.parent_department_id from departments WHERE id = 1
UNION ALL
SELECT d1.id,d1.department_name,d1.parent_department_id from departments d1 inner join departments_list d2 on d1.parent_department_id = d2.id
)
SELECT * FROM departments_list;
我写下来,我感觉要注意的几个问题一定要搞明白:
departments_list
的字段是怎么确定的? A:是第一个子SQL的Select字段决定的。参考文档:
教你如何使用 MySQL8 递归 - Java开发指北 - SegmentFault 思否