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

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

admin8个月前 (05-04)数码25

背景

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

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

预备

创立组织表:

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的用法)” 的相关文章

Java开发者的MySQL数据库版本管理策略-从规划到部署的全面指南 (java开发工程师)

Java开发者的MySQL数据库版本管理策略-从规划到部署的全面指南 (java开发工程师)

数据库是软件开发中常用的关系型数据库之一。版本管理是保障数据库稳定性和可靠性的重要方面。本文将介绍针对 Java 开发者的 MySQL 数据库版本管理策略,包括版本控制工具选择、数据库脚本管理、变...

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

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

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

主从复制原理简介-MySQL (主从复制原理mysql)

主从复制原理简介-MySQL (主从复制原理mysql)

主从复制(Master-SlaveReplication)是一种数据复制技术,用于在多个数据库主机之间的数据同步。在主从复制架构中,一个主机被设置为主主机(Master),充任数据源,其余主机被设...

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

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

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

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

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

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

运行系统 (列车自动运行系统)

运行系统 (列车自动运行系统)

作者:徐良,现任中国移动智慧家庭经营中心数据库初级经理,多年数据库运维优化阅历,历任华为、一线互联网公司初级DBA。目前关键担任中移智家基于规模的价值经营场景下数据库稳固性、容灾优化、他乡多活等相...

PostgreSQL-在中国的优势-的因素-MySQL-超越

PostgreSQL-在中国的优势-的因素-MySQL-超越

在全球范围内,MySQL 一直领先于 PostgreSQL (以下简称 PG)。DB-Engines 的趋势图显示,尽管 PG 是近 10 年增长最快的数据库,但 MySQL 仍保持着优势。从...

MySQL-自增主键的连续自增特性 (mysql-u-p)

MySQL-自增主键的连续自增特性 (mysql-u-p)

MySQL 中的 auto_increment_increment 设置用于指定自增主键递增的步幅大小。 默认值 auto_increment_increment 的默认值为 1,这意...