当前位置:首页 > 数码 > MySQL中经常使用递归查问轻松找到一切子节点 (mysql中DISTINCT的用法)

MySQL中经常使用递归查问轻松找到一切子节点 (mysql中DISTINCT的用法)

admin5个月前 (05-04)数码13

背景

名目中遇到一个需求,要求查出菜单节点的一切节点,在网上查了一下,大少数的方法用到了存储环节,由于线上环境不能随意参与存储环节。

因此在这里驳回相似递归的方法对组织下的一切子节点启动查问。

预备

创立组织表:

CREATETABLEgroups(`group_id`int(11)NOTNULLAUTO_INCREMENTCOMMENT'组织ID',`parent_id`int(11)DEFAULTNULLCOMMENT'父节点ID',`group_name`varchar(128)DEFAULTNULLCOMMENT'组织称号',PRIMARYKEY(`group_id`))ENGINE=InnoDBAUTO_INCREMENT=0DEFAULTCHARSET=utf8;

写入数据:

INSERTINTOgroupsVALUES(0,null,'系统治理组织');INSERTINTOgroupsVALUES(1,0,'中国电信股份有限公司');INSERTINTOgroupsVALUES(2,1,'万州分公司');INSERTINTOgroupsVALUES(3,1,'涪陵分公司');INSERTINTOgroupsVALUES(4,2,'龙都支局');INSERTINTOgroupsVALUES(5,2,'新田支局');INSERTINTOgroupsVALUES(6,3,'马武支局');INSERTINTOgroupsVALUES(7,3,'南沱支局');INSERTINTOgroupsVALUES(8,4,'党群上班部');INSERTINTOgroupsVALUES(9,5,'客户服务部');INSERTINTOgroupsVALUES(10,6,'洽购和供应链治理事业部');INSERTINTOgroupsVALUES(11,7,'网络和消息安保治理部');

树状结构:

-系统治理组织-中国电信股份有限公司-万州分公司-龙都支局-党群上班部-新田支局-客户服务部-涪陵分公司-马武支局-洽购和供应链治理事业部-南沱支局-网络和消息安保治理部

成功

查问

selectgroup_id,group_namefrom(selectt1.group_id,t1.parent_id,t1.group_name,t2.pids,if(find_in_set(parent_id,@pids)>0,@pids:=concat(@pids,',',group_id),0)asischildfrom(selectgroup_id,parent_id,group_namefrom`groups`)t1,(select@pids:=#{groupId}aspids)t2)t3whereischild!=0;

比如,要查问的万州分公司下一切子节点,只需将 #{groupId} 变卦为万州分公司的组织ID即可:

group_id|group_name|--------+----------+4|龙都支局|5|新田支局|8|党群上班部|9|客户服务部|

语句解析

group_id|parent_id|group_name|--------+---------+-----------+0||系统治理组织|1|0|中国电信股份有限公司|2|1|万州分公司|3|1|涪陵分公司|4|2|龙都支局|5|2|新田支局|6|3|马武支局|7|3|南沱支局|8|4|党群上班部|9|5|客户服务部|10|6|洽购和供应链治理事业部|11|7|网络和消息安保治理部|
pids|----+2|
group_id|parent_id|group_name|pids|ischild|--------+---------+-----------+----+---------+0||系统治理组织|2|0|1|0|中国电信股份有限公司|2|0|2|1|万州分公司|2|0|3|1|涪陵分公司|2|0|4|2|龙都支局|2|2,4|5|2|新田支局|2|2,4,5|6|3|马武支局|2|0|7|3|南沱支局|2|0|8|4|党群上班部|2|2,4,5,8|9|5|客户服务部|2|2,4,5,8,9|10|6|洽购和供应链治理事业部|2|0|11|7|网络和消息安保治理部|2|0|
group_id|group_name|--------+----------+4|龙都支局|5|新田支局|8|党群上班部|9|客户服务部|

8.0版本

MySQL中经常使用递归查问轻松找到一切子节点
WITHRECURSIVEsubordinatesAS(SELECTgroup_id,group_name,parent_idFROMgroupsWHEREparent_id=2--指定父节点IDUNIONALLSELECTg.group_id,g.group_name,g.parent_idFROMgroupsgINNERJOINsubordinatessONs.group_id=g.parent_id)SELECT*FROMsubordinates;
group_id|group_name|parent_id|--------+----------+---------+4|龙都支局|2|5|新田支局|2|8|党群上班部|4|9|客户服务部|5|

代码递归

@Testpublicvoidtest1(){List<Map<String,Object>>groupList=newArrayList<>();groupList=queryListParentId(2,groupList);System.out.println(groupList);groupList.clear();System.out.println("=====================");List<String>list=newArrayList<>();list.add("3");groupList=queryListParentId2(list,groupList);System.out.println(groupList);}//模式一,循环遍历查问publicList<Map<String,Object>>queryListParentId(IntegerparentId,List<Map<String,Object>>groupList){Stringsql="selectgroup_id,group_namefromgroupswhereparent_id="+parentId;List<Map<String,Object>>list=jdbcTemplate.queryForList(sql);if(!CollectionUtils.isEmpty(list)){groupList.addAll(list);for(Map<String,Object>map:list){queryListParentId((Integer)map.get("group_id"),groupList);}}returngroupList;}//模式二,经常使用find_in_set函数publicList<Map<String,Object>>queryListParentId2(List<String>parentId,List<Map<String,Object>>groupList){Stringjoin=String.join(",",parentId);Stringsql="selectgroup_id,group_namefromgroupswherefind_in_set(parent_id,'"+join+"')";List<Map<String,Object>>list=jdbcTemplate.queryForList(sql);if(!CollectionUtils.isEmpty(list)){groupList.addAll(list);List<String>collect=list.stream().map(map->map.get("group_id")+"").collect(Collectors.toList());queryListParentId2(collect,groupList);}returngroupList;}
[{group_id=4,group_name=龙都支局},{group_id=5,group_name=新田支局},{group_id=8,group_name=党群上班部},{group_id=9,group_name=客户服务部}]=====================[{group_id=6,group_name=马武支局},{group_id=7,group_name=南沱支局},{group_id=10,group_name=洽购和供应链治理事业部},{group_id=11,group_name=网络和消息安保治理部}]

在 SQL 中,你可以使用递归查询来实现递归函数。 递归查询是一种查询,其中结果集由一条或多条 SELECT 语句和一条用于查找下一级行的 UNION ALL 语句组成。 例如,假设你有一张表,其中包含父子关系的信息(即,每个记录都有一个父级 ID,表示它的父级),你可以使用以下递归查询来查询每个记录的所有祖先:WITH RECURSIVE ancestors AS (-- 初始查询SELECT id, parent_idFROM your_tableWHERE id = :your_idUNION ALL-- 递归查询SELECT , _idFROM your_table tINNER JOIN ancestors a ON = _id)SELECT id FROM ancestors;在这个查询中,我们使用了一个递归关系,其中第一个 SELECT 语句是初始查询,用于查询给定 ID 的记录。 第二个 SELECT 语句是递归查询,用于查询与当前记录的父级相关的记录。 通过将这两个 SELECT 语句用 UNION ALL 连接起来,我们就可以获得所有祖先的列表了。

免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。

标签: MySQL

“MySQL中经常使用递归查问轻松找到一切子节点 (mysql中DISTINCT的用法)” 的相关文章

MySQL-一探究竟-核心模块揭秘 (mysql-bin文件可以删除吗)

MySQL-一探究竟-核心模块揭秘 (mysql-bin文件可以删除吗)

Undo Segment Caching To improve the efficiency of undo segmentallocation, InnoDB caches some un...

优化数据统计的终极指南-MySQL-提升查询性能的秘诀 (优化数据统计工具)

优化数据统计的终极指南-MySQL-提升查询性能的秘诀 (优化数据统计工具)

在业务场景中,我们经常需要统计当前已有的业务数据,例如商品库内商品的数量、每天的用户订单数量等。此时,我们需要使用统计功能来实现。 count()实现方式 对于不同的数据库引擎,co...

实战-MySQL-数据库压力测试与性能评估方法-Java (实战篮球鞋排名)

实战-MySQL-数据库压力测试与性能评估方法-Java (实战篮球鞋排名)

压力测试的目的和重要性 压力测试是模拟真实环境中并发用户访问数据库的场景,通过增加负载来测试数据库系统的性能表现。压力测试的目的是发现数据库在高负载下的性能瓶颈、资源利用情况和响应时间等指...

如何在MySQL中成功数据的版本治理和回滚操作 (如何在mysql数据库中添加数据)

如何在MySQL中成功数据的版本治理和回滚操作 (如何在mysql数据库中添加数据)

成功数据的版本治理和回滚操作在中可以经过以下几种模式成功,包含经常使用事务、备份恢复、日志和版本控制工具等。上方将详细引见这些方法。 1.经常使用事务: MySQL允许事务操作,可以经...

使用-数据库并自动发送备份文件到指定邮箱-K8s-定期备份-MySQL (使用数据库的命令)

使用-数据库并自动发送备份文件到指定邮箱-K8s-定期备份-MySQL (使用数据库的命令)

简介 本文档描述了一个使用脚本来监控服务器高占用率进程并通过电子邮件发送警报的项目。本文还探讨了使用相同机制备份数据库的可能性。 技术 Python psuti...

MySQL-实现非中断亿级数据处理的秘密 (mysql-bin文件可以删除吗)

MySQL-实现非中断亿级数据处理的秘密 (mysql-bin文件可以删除吗)

MySQL 在海量数据管理方面表现得非常出色,能够存储上亿级别的数据,同时还具有极高的数据可靠性,几乎不会发生数据丢失的情况。这一强大的特性离不开 MySQL 的两大日志系统:binlog 和 r...

揭秘MySQL中Varchar和Int的隐式转换 (揭秘国安部点名的间谍机构)

揭秘MySQL中Varchar和Int的隐式转换 (揭秘国安部点名的间谍机构)

前言 在一次例行测试中,我们遇到了一个奇特的现象。一条查询库存数量的SQL语句,居然返回了0条记录。当我们手工执行SQL时,却查询到了一条记录。调查发现,原因在于MySQL的优化器在判断数据类型...

揭开其背后的神奇世界-深入探寻-索引的底层逻辑-MySQL (揭开其背后的真相)

揭开其背后的神奇世界-深入探寻-索引的底层逻辑-MySQL (揭开其背后的真相)

什么是索引? 索引是数据库系统中一种特殊的数据结构,用于快速查找数据。索引以某种方式引用(指向)数据,允许在索引上实现高级查找算法,从而提高查询速度。 索引的种类 最常见的索引类型有:...