MySql 递归查询

131 阅读2分钟

递归查询理解

image.png

image.png

每一步理解

当使用 RECURSIVE 关键字执行递归查询时,每一步的结果都会被迭代地添加到结果集中,直到满足递归结束条件。

下面是一个使用 RECURSIVE 的示例,假设有一个名为 categories 的表,包含分类的 ID 和父分类的 ID:

CREATE TABLE categories (
  id INT,
  name VARCHAR(50),
  parent_id INT
);

现在,我们想要获取一个分类及其所有的子分类(子分类的子分类等),我们可以使用 RECURSIVE 关键字来执行递归查询:

WITH RECURSIVE category_tree AS (
  SELECT id, name, parent_id
  FROM categories
  WHERE id = 1  -- 假设要获取分类 ID 为 1 的分类及其子分类
  UNION ALL
  SELECT c.id, c.name, c.parent_id
  FROM categories c
  INNER JOIN category_tree ct ON c.parent_id = ct.id
)
SELECT * FROM category_tree;

在上面的查询中,我们使用了一个公共表表达式(Common Table Expression,CTE),其中使用 RECURSIVE 关键字定义了一个名称为 category_tree 的递归查询。递归查询包含两个部分:

  1. 初始查询(Anchor Query):它是递归查询的起点。在上述示例中,初始查询选择了分类 ID 为 1 的记录。
  2. 递归查询(Recursive Query):它引用了 CTE 自身,并根据关联条件将子分类添加到结果集中。

在递归查询中,我们使用 UNION ALL 运算符将初始查询和递归查询的结果合并在一起。每次递归迭代时,子分类的记录会被添加到结果集中,并继续进行下一次迭代,直到没有更多的子分类满足条件。

下面是一个示例结果集的逐步生成过程:

初始查询:

id | name       | parent_id
---+------------+----------
1  | Electronics| NULL

第一次递归查询:

id | name            | parent_id
---+-----------------+----------
2  | Computers       | 1
3  | Mobile Phones   | 1
4  | Televisions     | 1

第二次递归查询:

id | name            | parent_id
---+-----------------+----------
5  | Laptops         | 2
6  | Desktops        | 2
7  | Smartphones     | 3
8  | Feature Phones  | 3
9  | LED             | 4
10 | OLED            | 4

以此类推,根据分类之间的父子关系,递归查询会继续迭代并返回所有满足条件的子分类,直到没有更多的子分类符合条件。

最后,主查询选择了 category_tree 表,它包含了递归查询的结果,即分类 ID 为 1 的分类及其所有子分类的记录。

UNION ALL 解析

试验了一下,列数一样就可以用 union all 结果合并。 image.png

查询树形结构,以自己为开头的 id hierarchy

image.png

image.png