📅  最后修改于: 2023-12-03 15:17:46.688000             🧑  作者: Mango
递归 CTE(通用表表达式)是 MySQL 中一种特殊的查询语言,用来处理层级结构(例如组织结构、分类、树形结构等)的数据。递归 CTE 使用起来非常方便,可以快速、简单地对层级结构数据进行查询和处理,同时也可以提高查询效率,避免使用循环等复杂的操作。
递归 CTE 利用 WITH 语句声明一个或多个递归公共表达式(recursive common table expression)。每个递归公共表达式包含两个部分,分别为递归条件和递归查询部分,如下所示:
WITH RecursiveCTE (column1, column2, ..., columnN) AS (
-- Non-Recursive part
SELECT column1, column2, ..., columnN
FROM table_name
WHERE condition
UNION ALL
-- Recursive part
SELECT column1, column2, ..., columnN
FROM table_name
JOIN RecursiveCTE
WHERE recursive_condition
)
SELECT column1, column2, ..., columnN
FROM RecursiveCTE
其中:
RecursiveCTE
:递归公共表达式的名称。column1, column2, ..., columnN
:递归公共表达式所包含的列。table_name
:需要进行递归查询的表名。condition
:查询所需的条件。recursive_condition
:递归查询中的条件,通常是指通过某个列的关系进行递归查询。假设有一张组织结构表 departments
,包含以下列:
id
:部门 ID。name
:部门名称。parent_id
:父部门 ID,如果为 NULL 则表示该部门为公司的顶级部门。现在,我们需要查询指定部门(例如 ID=1)的所有子部门及其子部门的子部门,可以使用以下 SQL:
WITH RecursiveDepartments (id, name, path) AS (
-- Non-Recursive part
SELECT id, name, CAST(name AS CHAR(100)) AS path
FROM departments
WHERE id = 1
UNION ALL
-- Recursive part
SELECT d.id, d.name, CONCAT(dp.path, ' > ', d.name)
FROM departments AS d
JOIN RecursiveDepartments AS dp
WHERE d.parent_id = dp.id
)
SELECT name, path
FROM RecursiveDepartments
ORDER BY path;
以上 SQL 语句中,我们使用了以下技巧实现递归查询:
CAST(name AS CHAR(100)) AS path
进行类型转换,以便在后面递归查询时能够正确拼接部门名称的路径。CONCAT(dp.path, ' > ', d.name)
对每个部门进行路径拼接。假设有一张树形结构表 categories
,包含以下列:
id
:节点 ID。name
:节点名称。parent_id
:父节点 ID,如果为 NULL 则表示该节点为根节点。现在,我们需要查询指定节点(例如 ID=5)的所有父节点及其祖先节点,以及所有子节点及其子孙节点,可以使用以下 SQL:
WITH RecursiveCategories (id, name, parent_category_id, level, path) AS (
-- Non-Recursive part
SELECT id, name, parent_category_id, 0, CAST(id AS CHAR(100)) AS path
FROM categories
WHERE id = 5
UNION ALL
-- Recursive part
SELECT c.id, c.name, c.parent_category_id, dc.level + 1, CONCAT(dc.path, ' > ', c.id)
FROM categories AS c
JOIN RecursiveCategories AS dc
WHERE c.parent_category_id = dc.id
OR c.id = dc.parent_category_id
)
SELECT id, name, parent_category_id, level, path
FROM RecursiveCategories
ORDER BY path;
以上 SQL 语句中,我们使用了以下技巧实现递归查询:
level
列,用来记录节点的层级关系。CAST(id AS CHAR(100)) AS path
对节点 ID 进行类型转换,以便在后面递归查询时能够正确拼接节点 ID 的路径。c.parent_category_id = dc.id OR c.id = dc.parent_category_id
条件判断是否存在父、子节点关系。使用递归 CTE 进行层级查询时需要注意以下事项:
递归 CTE 是 MySQL 中处理层级结构数据的有力工具,让程序员能够快速、简单地对数据进行查询和处理。利用递归 CTE,我们可以轻松实现组织架构、分类、树形结构等数据的查询和统计,提高编程效率,实现更好的程序设计。