【代码备忘录】SQL 中的递归写法案例

本文核心知识点

SQL 中的递归 CTE,WITH RECURSIVE

不废话,有兴趣就直接跳到文末【参考文献】部分,中间内容为我的练习过程。

前言

复盘(马后炮)一下,给自己以后写复杂SQL时留点案例。

以下案例均为胡说八道,会有逻辑漏洞,如有雷同皆为巧合~

以下解法仅考虑实现,未涉及性能~

写挺乱的。

信息

数据库版本

Mysql 8.0.31

数据表结构

person 族人表id 主键 name 姓名

consanguinity 血缘表id 主键 this_id 来源id source_id 指向id name 血缘名称

现有数据

person

id name
1 张三
2 张三三
3 张重三
4 王二
5 王三
6 王小妹

consanguinity

id this_id source_id name
1 2 1 父亲
2 3 2 父亲
3 4 1 舅父
4 5 4 父亲
5 6 5 大伯

需求

查询某个人的所有后代。

输出示例

例如 查询人为【张三】。

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 RECURSIVESQL中用于定义递归公共表达式(CTE)的关键字。递归公共表达式允许在查询中递归引用自身,从而处理层次结构或递归关系的数据。

在这个例子中,WITH RECURSIVE 用于定义名为 descendants 的递归公共表达式。

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

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

可以在递归公共表达式之后的主查询中引用 descendants 表,并执行进一步的操作。

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

新学到的知识

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

基本语法结构

WITH RECURSIVE 的基本语法结构如下:

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:最终查询部分,用于从递归结果集中选择所需的列进行进一步的分析或操作。

参考文献

[1] . WITH (Common Table Expressions) . MySQL官方文档 . https://dev.mysql.com/doc/refman/8.0/en/with.html
[1] . Queries (Common Table Expressions)WITH . postgresql官方文档 . https://www.postgresql.org/docs/current/queries-with.html
[3] . Recursive SQL Expression Visually Explained  . Denis Lukichev . https://builtin.com/data-science/recursive-sql
[4] . The WITH Clause . sqlite官方文档 . https://www.sqlite.org/lang_with.html
[5] . What Is a Recursive CTE in SQL? . Tihomir Babic . https://learnsql.com/blog/sql-recursive-cte/
[6] . with recursive实现导航栏 . 孤鸿君 . CSDN . https://blog.csdn.net/weixin_42345223/article/details/119534624
[7] . SQL中with recursive用法案例详解 . Lee Howard . CSDN . https://blog.csdn.net/pilihaotian/article/details/128313615


原文始发于微信公众号(左羊公社):【代码备忘录】SQL 中的递归写法案例

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/187438.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!