• SQL 中如何实现递归查询
  • 发布于 2个月前
  • 160 热度
    0 评论
前言
复盘一下,给自己以后写复杂SQL时留点案例。以下案例均为胡说八道,会有逻辑漏洞,如有雷同皆为巧合,以下解法仅考虑实现,未涉及性能。

信息
1.数据库版本
Mysql 8.0.31
2.表信息

需求
查询某个人的所有后代。

输出示例
例如 查询人为【张三】。
id name
2 张三三
3 张重三
4 王二
5 王三
6 王小妹
SQL
WITH RECURSIVE descendants AS (
  SELECT p.id, p.name
  FROM person p
 Left JOIN consanguinity c ON c.this_id = p.id
  WHERE c.source_id = 1
  UNION ALL
  SELECT p.id, p.name
  FROM descendants d
  JOIN consanguinity c ON c.source_id = d.id
  JOIN person p ON c.this_id = p.id
)
SELECT DISTINCT *
FROM descendants;
SQL解析
WITH RECURSIVE descendants AS (
  -- Recursive term
  -- 递归术语
  SELECT p.id, p.name
  FROM person p
  LEFT JOIN consanguinity c ON c.this_id = p.id
  WHERE c.source_id = 1
  
  UNION ALL
  -- Recursive part
  -- 递归部分
  
  SELECT p.id, p.name
  FROM descendants d
  JOIN consanguinity c ON c.source_id = d.id
  JOIN person p ON c.this_id = p.id
)
WITH RECURSIVE 是SQL中用于定义递归公共表达式(CTE)的关键字。递归公共表达式允许在查询中递归引用自身,从而处理层次结构或递归关系的数据。在这个例子中,WITH RECURSIVE 用于定义名为 descendants 的递归公共表达式。

递归术语(Recursive term):定义起始查询部分,它基于 person 和 consanguinity 表,选择与指定 source_id 匹配的记录(这里是1,也就是张三的ID),并返回对应的 id 和 name。

递归部分(Recursive part):基于之前递归结果集 descendants,通过与 consanguinity 和 person 表的连接,选择与之前结果集中的 id 匹配的记录,并返回对应的 id 和 name。这个部分的目的是递归地获取后代的信息。

可以在递归公共表达式之后的主查询中引用 descendants 表,并执行进一步的操作。递归公共表达式是对递归查询的一种结构化方式,它使得处理层次结构数据和树型数据变得更加方便。在使用 WITH RECURSIVE 时需要小心,确保设置递归终止条件,以避免无限递归和性能问题。

新学到的知识
WITH RECURSIVE 是 SQL 语言中用于定义递归公共表达式(CTE)的关键字。递归公共表达式允许在查询中进行递归引用,从而处理层次结构、递归关系或链式关系的数据。

基本语法结构
WITH RECURSIVE 的基本语法结构如下:
--堆代码 duidaima.com --
WITH RECURSIVE cte_name (column1, column2, ...) AS (
  -- 初始查询部分
  SELECT initial_columns
  FROM initial_table
  WHERE condition
  
  UNION [ALL]
  
  -- 递归查询部分
  SELECT recursive_columns
  FROM cte_name
  JOIN recursive_table ON join_condition
  WHERE recursive_condition
)
SELECT final_query_columns
FROM cte_name
对于 WITH RECURSIVE 的用法,我们可以了解以下几点:
cte_name:递归公共表达式的名称,可以在主查询中引用这个名称。
column1, column2, ...:定义递归结果集的列名。
initial_query:初始查询部分,用于获取递归的起点数据。
initial_table:初始查询部分所关联的表。
condition:用于过滤 initial_table 中的记录。
UNION [ALL]:指定递归部分与初始查询部分的关系,ALL 表示保留所有重复的记录,而不仅仅是不重复的记录。
recursive_query:递归查询部分,用于根据已经计算的结果进行进一步的递归操作。
recursive_table:递归查询部分所关联的表。
join_condition:用于连接递归结果集和递归表之间的关联条件。
recursive_condition:用于过滤递归查询部分所关联表的记录,以控制递归的终止条件。
final_query:最终查询部分,用于从递归结果集中选择所需的列进行进一步的分析或操作。
用户评论