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递归查询超详细--保姆级别讲解

相关推荐
Joy T9 小时前
Redis Lua 原子限流:Lua 脚本、竞态条件与并发控制
数据库·redis·lua·限流·竞态条件·redis scripting
杨凯凡9 小时前
MySQL 死锁怎么排查?InnoDB 锁等待与 Spring Boot 整事务重试实战
数据库·spring boot·mysql
Aloudata9 小时前
Claude 做数据分析的这两年:一份复盘与发展线索
大数据·数据库·人工智能·数据挖掘·数据分析·dataagent
Decay__9 小时前
01_SQLServer 体系架构全解 —— 实例进程、关系引擎、SQLOS 与事务日志深入
运维·数据库·sql·mysql·架构
zhanghaha13149 小时前
C# 系列教程_12 字符串 string 保姆级系统教程(面向新手,大量示例 + 原理讲解)
开发语言·数据库·c#
韩曙亮10 小时前
【错误记录】安卓 adb 调试 5037 端口占用排查 ( adb 的三层结构 | 找出本机占用 5037 的进程 )
android·数据库·adb·安卓·错误记录
瑞雪兆丰年兮10 小时前
JavaWeb-day07-MySQL(DQL&多表设计)
java·开发语言·数据库·sql·mysql·javaweb·web
lsc_blog15 小时前
年终自评别贴提交记录,把技术产出讲成变化
数据库·面试·职场和发展·跳槽·求职招聘
FungLeo18 小时前
成为全栈·基础补充·数据库迁移与事务:数据结构怎样安全演进
mysql·postgresql·sqlite·数据一致性·数据库事务·数据库迁移·成为全栈
Zan1 天前
SQLite + SQLx 实战:为什么已经发布的数据库迁移文件,绝对不能再修改?
数据库·后端·面试