mysql之递归sql

mysql之递归sql

递归sql在一些公司是不允许使用的,会涉及数据库压力,所以会在代码里递归查询,但有些公司开发流程没有规定,且数据库数据量不大,之前写过好几遍了,老是记不住,记录一下

通过父级id查询所有子集(不包括父级)

方案一:不带查询的本层级

sql 复制代码
# 0.4s
select  id,
        name,
        parent_id 
from    (select * from products # 表名
         order by parent_id, id) products_sorted,
        (select @pv := '你的id') initialisation
where   find_in_set(parent_id, @pv)
and     length(@pv := concat(@pv, ',', id))

方案二:带查询本层级

sql 复制代码
# 1.55s
SELECT
	ID.LEVEL,
	org.* 
FROM
	(
	SELECT
		@ids AS _ids,
		( SELECT @ids := GROUP_CONCAT( id ) FROM sys_org WHERE FIND_IN_SET(parent_id, @ids ) ) AS cids,
		@l := @l + 1 AS LEVEL 
	FROM
		sys_org,
		( SELECT @ids := '查询的id', @l := 0 ) b 
	WHERE
		@ids IS NOT NULL 
	) ID,
	sys_org org 
WHERE
	FIND_IN_SET( org.id, ID._ids ) 
ORDER BY
	LEVEL

从子集向上递归

方案一:

sql 复制代码
SELECT T2.id, T2.name, T2.parent_id,T1.lvl
FROM
	(
	SELECT
		@r AS rid,
	  (SELECT @r := parent_id FROM sys_org WHERE id = rid) AS parent_id,
		@l := @l + 1 AS lvl 
	FROM
		( SELECT @r := '你要查询的id', @l := 0 ) vars,
		sys_org h #递归表
	WHERE
		@r <> 0 #父id条件
	) T1
	JOIN sys_org T2 ON T1.rid = T2.id 
ORDER BY
	T1.lvl DESC

方案二:

sql 复制代码
SELECT T2.id, T2.parent_id, T2.name
FROM (SELECT @r AS _id, (SELECT @r := parent_id FROM sys_org WHERE id = _id) AS parent_id
        FROM (SELECT @r := '你要查询的id') vars,
        sys_org h WHERE @r <> 0) T1 JOIN sys_org T2 ON T1._id = T2.id

mysql8.0神级递归

sql 复制代码
 
WITH RECURSIVE org_tree (id,parent_id) AS (

# 初始查询,选择根节点(例如,没有父节点的节点)  
  SELECT id, parent_id
  FROM sys_org #要递归的表明
  WHERE parent_id = 0 #递归的父id
 
  UNION ALL
 
  -- 递归查询,选择当前层级的子节点
  SELECT o.id, o.parent_id
  FROM sys_org o
  INNER JOIN org_tree ot ON o.parent_id = ot.id
)
SELECT * FROM org_tree;

# 查询mysql版本
SELECT VERSION();

这里 org_tree为虚拟表,在递归部分,我们先通过一个初始查询(sys_org )得到一些初始的结果。然后我们通过UNION ALL运算将初始结果集合并到递归查询结果中。接下来,在每次递归查询中,我们使用前一次递归的结果(org_tree)与递归查询(sys_org )进行运算,并使用WHERE条件过滤掉不需要的数据。最后,在终止条件部分中,我们使用一个条件来判断递归查询何时停止。当递归查询到终止条件时,递归查询结束,最终结果被返回

WITH RECURSIVE:

表示要使用递归查询的方式处理数据。

UNION:

表示将两个查询结果集进行联合,使用UNION ALL则表示保留重复数据。

SELECT * FROM 临时表:

表示最终返回的查询结果集,可以通过临时表查询表中的列名进行指定。

如果还是不是很理解可以参考:MySQL递归查询超详细--保姆级别讲解

相关推荐
zcmodeltech28 分钟前
工程机械与矿山机械沙盘模型多系统协同控制系统设计:基于STM32与Modbus RTU的露天开采-井下掘进-智慧矿山全场景联动方案
数据库·stm32·单片机·嵌入式硬件·制造·多分类
曹牧40 分钟前
Oracle:空值排序
数据库·oracle
SelectDB1 小时前
Apache Doris 与 StarRocks 深度对比:2026 年 OLAP 引擎选型指南
数据库
lbb 小魔仙1 小时前
谁替 AI Agent 记住时间?——从航海钟到智能数据库,三百年时延坍缩史
数据库·人工智能·db
Csvn1 小时前
📊 SQL 入门 Day 19:事务与隔离级别
后端·sql
这个DBA有点耶1 小时前
读懂半连接:IN/EXISTS子查询什么时候快、什么时候慢?
数据库·性能优化·架构
01_ice1 小时前
MySQL内外连接
数据库·mysql
ClouGence2 小时前
2026 年 4 款数据库管理工具推荐:免费、开源、付费怎么选?
数据库·后端·开源
SelectDB3 小时前
招联金融数仓升级:Apache Doris 统一 OLAP 引擎实现降本提效实践
数据库
SelectDB3 小时前
腾讯音乐内容库 ES 替代:从 Elasticsearch 到 Apache Doris 统一搜索分析引擎实践
数据库