SQL递归查询

引言

递归查询通常用于树形结构数据的查询。很多数据库(PG、MYSQL、SQLSERVER)都支持使用通用表表达式(CTE)(WITH RECURSIVE) 关键字实现递归查询。

CTE(Common Table Expressions,通常使用With开头,允许在查询中创建可被引用的临时表。

递归查询的一般形式

递归查询是通过在CTE中添加RECURSIVE关键字实现的,其一般形式如下:

sql 复制代码
WITH RECURSIVE cte_name AS (
  non_recursive_term
  UNION [ALL]
  recursive_term
)
invocation_statement

其中,

  • cte_name是用于实现递归查询的一个公共表表达式的名称;
  • non_recursive_term 非递归项
  • recursive_term 递归项
  • nvocation_statement则是公共表表达式的调用语句

Postgresql递归查询的执行过程

本部分内容摘自PGSQL官网文档

  1. 执行非递归项,将返回的结果记为 <math xmlns="http://www.w3.org/1998/Math/MathML"> R i R_i </math>Ri(此时 <math xmlns="http://www.w3.org/1998/Math/MathML"> i i </math>i=0)。
  2. 重复以下步骤,直至满足递归终止条件:
    1. 检查 <math xmlns="http://www.w3.org/1998/Math/MathML"> R i R_i </math>Ri是否为空,如果为空则终止递归,直接跳到步骤3。
    2. 将 <math xmlns="http://www.w3.org/1998/Math/MathML"> R i R_i </math>Ri替换递归项中的递归自引用,然后执行递归项,(如果使用了UNION而非UNION ALL,则会自动去除与之前结果行重复的行,并将返回的剩余记录记为 <math xmlns="http://www.w3.org/1998/Math/MathML"> R i + 1 R_{i+1 } </math>Ri+1。
    3. 记 <math xmlns="http://www.w3.org/1998/Math/MathML"> i i </math>i= <math xmlns="http://www.w3.org/1998/Math/MathML"> i i </math>i+1。

【实践】记录一次工作中碰到的树结构递归查询死循环问题

一个类似这样的数据表:

id pid
A B
B A

使用这样的递归查询语句:

sql 复制代码
WITH RECURSIVE TEST (
  SELECT id,pid from tree
  union all -- union all会返回所有的数据,不进行去重操作
  select id,pid from tree left join TEST on tree.id = TEST.pid
)
selct * from TEST

理论上这样的SQL会无限循环,实际执行时也是这样。但只要把union all 改为 union,sql查询很快就会返回结果了。

推测:union 去重操作也会影响终止条件,推测是数据库引擎内部会把UNION后的结果集 <math xmlns="http://www.w3.org/1998/Math/MathML"> R i + 1 R_{i+1 } </math>Ri+1 与上一次递归循环结果集 <math xmlns="http://www.w3.org/1998/Math/MathML"> R i R_i </math>Ri进行比较。
PS:后边查询官网的执行过程也印证了这个说法。

相关推荐
养生技术人4 小时前
Oracle OCP认证考试题目详解082系列第57题
运维·数据库·sql·oracle·开闭原则
EnCi Zheng6 小时前
SpringBoot + PostgreSQL 密码认证失败 Windows 系统解决方案
windows·spring boot·postgresql
养生技术人8 小时前
Oracle OCP认证考试题目详解082系列第53题
数据库·sql·oracle·database·开闭原则·ocp
豆沙沙包?11 小时前
2025年--Lc171--H175 .组合两个表(SQL)
数据库·sql
养生技术人15 小时前
Oracle OCP认证考试题目详解082系列第48题
运维·数据库·sql·oracle·database·开闭原则·ocp
工作中的程序员18 小时前
hive sql优化基础
hive·sql
杨云龙UP18 小时前
小工具大体验:rlwrap加持下的Oracle/MySQL/SQL Server命令行交互
运维·服务器·数据库·sql·mysql·oracle·sqlserver
阿巴~阿巴~18 小时前
使用 C 语言连接 MySQL 客户端(重点)
服务器·数据库·sql·mysql·ubuntu
清水加冰18 小时前
【MySQL】SQL调优-如何分析SQL性能
数据库·sql·mysql
风跟我说过她18 小时前
CentOS 7 环境下 MySQL 5.7 深度指南:从安装、配置到基础 SQL 操作
sql·mysql·centos