MYSQL递归查询,根据子类ID查询所有父类(宇宙第一详细教程)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: MYSQL递归查询,根据子类ID查询所有父类(宇宙第一详细教程)

前言


工作中业务需求碰到了MYSQL递归这个点,网上资料大都抄来抄去,虽然代码的确能运行。但是萌新是真的看不懂这SQL写的什么玩意啊,看底下评论很多人提问皆是未回复,自己狠下心花了一上午时间,把这个点总结整理了一下,希望能给以后工作学习中遇到MYSQL递归一头雾水像我一样的萌新们一点小小的帮助。


数据表结构


id    name  parent_id


1        A        0

2        B        1

3        C        1

4        D        2

5        E        4

6        F        1

7        G        1


注:parent_id 为0表示顶级父节点,即A是顶级父辈,没有父节点


转储SQL表结构及数据


SET FOREIGN_KEY_CHECKS=0;


-- ----------------------------

-- Table structure for demo

-- ----------------------------

DROP TABLE IF EXISTS `demo`;
CREATE TABLE `demo` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `parent_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;


-- ----------------------------

-- Records of demo

-- ----------------------------

INSERT INTO `demo` VALUES ('1', 'A', '0');
INSERT INTO `demo` VALUES ('2', 'B', '1');
INSERT INTO `demo` VALUES ('3', 'C', '1');
INSERT INTO `demo` VALUES ('4', 'D', '2');
INSERT INTO `demo` VALUES ('5', 'E', '4');
INSERT INTO `demo` VALUES ('6', 'F', '1');
INSERT INTO `demo` VALUES ('7', 'G', '1');

需求:根据一个子ID,查询所有父类


SQL如下:


SELECT T2.id, T2.name 
FROM ( 
    SELECT 
        @r AS _id, 
        (SELECT @r := parent_id FROM demo WHERE id = _id) AS parent_id, 
        @l := @l + 1 AS lvl 
    FROM 
        (SELECT @r := 5, @l := 0) vars, 
        demo h 
    WHERE @r <> 0) T1 
JOIN demo T2 
ON T1._id = T2.id 
ORDER BY T1.lvl DESC 

结果如下


id      name

1         A

2         B

4         D

5         E


分析过程(答疑过程)


我使用将SQL语句拆分的方式,并展示每句SQL运行结果,让各位可以看的更明白,以便于根据你自己的业务需求进行更改


1、先不管T2,先把T1的SQL抽出来看


SELECT 
        @r AS _id, 
        (SELECT @r := parent_id FROM demo WHERE id = _id) AS parent_id, 
        @l := @l + 1 AS lvl 
    FROM 
        (SELECT @r := 5, @l := 0) vars, 
        demo h 
    WHERE @r <> 0

运行结果



从这里可以看出,其实T1已经找出ID为5节点的所有父节点了,和T2(即demo表)进行左连接,只不过是为了根据Id获取Name而已。而且还可以看出@l其实在整个SQL中并没有什么作用,只是用来标识节点的等级,底级子节点的lvl为1,父节点lvl值越大表示越靠近顶级父节点,想象一下树结构,你就明白了


2、搞明白@r := 5


SELECT @r := 5, @l := 0

运行结果



从这里看出,其实@r,@l 就是一个变量而已,


作为变量自然你可以随便起名,当然也可以随便赋值,改成@a,@b也都是可以的


那这句SQL的意思就出来了,它表示给变量@r赋值,值为5,给@l赋值,值为0


因此,其实整个SQL的意思也明了了就是根据子ID5,查询所有父类


3、搞懂变量@r 值如何变化


@r AS _id,
(SELECT @r := parent_id FROM demo WHERE id = _id) AS parent_id


根据MYSQL执行顺序(在文章末尾处),SQL语句在执行时会先执行From,即会先执行上一步的赋值操作,因此这里的_id值为5,所以上面的SQL等同于如下SQL


SELECT @r := parent_id FROM demo WHERE id = 5

运行结果



这句SQL肯定没人不会,但是有一个点很重要,它是整个执行过程的核心,就是@r := parent_id,它在查询Id为5的节点的父Id时,把这个父Id同时赋给了变量@r。因此@r值改变了,它从5变为了4。


这个时候思路就很清晰了,只要我们设置限制条件,让SQL在@r为0的时候结束循环就OK了


4、<>符号的含义


WHERE @r <> 0

这个就没什么好说的了,<>符号在MYSQL中表示不等于,这就是我们在第四步中所说的限制条件,它限制了@r这个变量不能等于0。所以当@r不等于0时,SQL语句会根据子ID向上查询父ID,又把父ID当做子ID赋值给@r,再次向上查询,直至@r变量的值为0为止。


补充:如果业务不需要,可以完全可以去掉@l变量


SELECT ,
        @a AS _id, 
        (SELECT @a := parent_id FROM demo WHERE id = _id) AS parent_id
    FROM 
        (SELECT @a := 5) vars, 
        demo h 
    WHERE @a <> 0

运行结果



可以看出@l其实在整个SQL中并没有什么作用,只是用来标识节点的等级,这也证实了我们上述第一步的关于@l的解释


因为这个过程很类似于JAVA通过构造树结构向上递归查询的方式,所以这个SQL形式被很多人叫做MYSQL递归查询


文章结尾


关于MYSQL的查询顺序


FROM
ON
JOIN
WHERE
GROUP By
CUBE|ROllUP
HAVING
SELECT
DISTINCT
ORDER BY
LIMIT

最先执行的是FROM操作,最后执行的是LIMIT操作。每个操作都会产生一个虚拟表,该虚拟表作为一个处理的输入


相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
26天前
|
存储 关系型数据库 MySQL
【免费动手教程上线】阿里云RDS MySQL推出大容量高性能存储:高性能本地盘(最高16TB存储空间)、高性能云盘(最高64TB存储空间)
阿里云RDS MySQL提供高性能本地盘与高性能云盘等存储方案,满足用户大容量、低延迟需求。高性能本地盘单盘最大16TB,IO延时微秒级;高性能云盘兼容ESSD特性,支持IO性能突发、BPE及16K原子写等能力。此外,阿里云还提供免费动手体验教程,帮助用户直观感受云数据库 RDS 存储性能表现。
|
27天前
|
缓存 JSON 关系型数据库
MySQL 查询优化分析 - 常用分析方法
本文介绍了MySQL查询优化分析的常用方法EXPLAIN、Optimizer Trace、Profiling和常用监控指标。
|
3月前
|
人工智能 关系型数据库 MySQL
解决MySQL自增id用尽的问题
本文介绍了解决文章点击记录表(`article_click_record`)数据量激增问题的方案。由于用户量大,每天新增约400万条记录,导致表id接近溢出(2,100,000,000),且占用空间超320G。解决方案包括:1) 新建`article_click_record_new`表,将id类型改为BIGINT以避免溢出;2) 过渡阶段同时写入新旧表,待旧表id溢出后切换至新表;3) 定时清理过期数据或转移旧表内容。实现方式涉及修改相关接口和服务逻辑,确保业务平稳过渡。
104 5
|
4月前
|
算法 关系型数据库 MySQL
join查询可以⽆限叠加吗?MySQL对join查询有什么限制吗?
大家好,我是 V 哥。本文详细探讨了 MySQL 中 `JOIN` 查询的限制及其优化方法。首先,`JOIN` 查询不能无限叠加,存在资源(CPU、内存、磁盘 I/O)、性能和语法等方面的限制。过多的 `JOIN` 操作会导致数据库性能急剧下降。其次,介绍了三种常见的 `JOIN` 查询算法:嵌套循环连接(NLJ)、索引嵌套连接(INL)和基于块的嵌套循环连接(BNL),并分析了它们的触发条件和性能特点。最后,分享了优化 `JOIN` 查询的方法,包括 SQL 语句优化、索引优化、数据库配置调整等。关注 V 哥,了解更多技术干货,点赞👍支持,一起进步!
|
6月前
|
SQL 关系型数据库 MySQL
【MySQL基础篇】多表查询(隐式/显式内连接、左/右外连接、自连接查询、联合查询、标量/列/行/表子查询)
本文详细介绍了MySQL中的多表查询,包括多表关系、隐式/显式内连接、左/右外连接、自连接查询、联合查询、标量/列/行/表子查询及其实现方式,一文全面读懂多表联查!
【MySQL基础篇】多表查询(隐式/显式内连接、左/右外连接、自连接查询、联合查询、标量/列/行/表子查询)
|
5月前
|
缓存 关系型数据库 MySQL
【深入了解MySQL】优化查询性能与数据库设计的深度总结
本文详细介绍了MySQL查询优化和数据库设计技巧,涵盖基础优化、高级技巧及性能监控。
1199 1
|
6月前
|
NoSQL Java 关系型数据库
Liunx部署java项目Tomcat、Redis、Mysql教程
本文详细介绍了如何在 Linux 服务器上安装和配置 Tomcat、MySQL 和 Redis,并部署 Java 项目。通过这些步骤,您可以搭建一个高效稳定的 Java 应用运行环境。希望本文能为您在实际操作中提供有价值的参考。
375 26
|
6月前
|
SQL 关系型数据库 MySQL
MySQL 窗口函数详解:分析性查询的强大工具
MySQL 窗口函数从 8.0 版本开始支持,提供了一种灵活的方式处理 SQL 查询中的数据。无需分组即可对行集进行分析,常用于计算排名、累计和、移动平均值等。基本语法包括 `function_name([arguments]) OVER ([PARTITION BY columns] [ORDER BY columns] [frame_clause])`,常见函数有 `ROW_NUMBER()`, `RANK()`, `DENSE_RANK()`, `SUM()`, `AVG()` 等。窗口框架定义了计算聚合值时应包含的行。适用于复杂数据操作和分析报告。
309 11
|
6月前
|
存储 Oracle 关系型数据库
索引在手,查询无忧:MySQL索引简介
MySQL 是一款广泛使用的关系型数据库管理系统,在2024年5月的DB-Engines排名中得分1084,仅次于Oracle。本文介绍MySQL索引的工作原理和类型,包括B+Tree、Hash、Full-text索引,以及主键、唯一、普通索引等,帮助开发者优化查询性能。索引类似于图书馆的分类系统,能快速定位数据行,极大提高检索效率。
132 8
|
6月前
|
存储 关系型数据库 MySQL
MySQL主键谁与争锋:MySQL为何钟爱自增主键ID+UUID?
本文深入探讨了在MySQL中使用自增类型主键的优势与局限性。自增主键通过保证数据的有序性和减少索引维护成本,提升了查询和插入性能,简化了数据库管理和维护,并提高了数据一致性。然而,在某些业务场景下,如跨表唯一性需求或分布式系统中,自增主键可能无法满足要求,且存在主键值易预测的安全风险。因此,选择主键类型时需综合考虑业务需求和应用场景。
212 2

推荐镜像

更多