MySQL中经常使用递归查问轻松找到一切子节点 (mysql中DISTINCT的用法)
背景
名目中遇到一个需求,要求查出菜单节点的一切节点,在网上查了一下,大少数的方法用到了存储环节,由于线上环境不能随意参与存储环节。
因此在这里驳回相似递归的方法对组织下的一切子节点启动查问。
预备
创立组织表:
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版本
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 连接起来,我们就可以获得所有祖先的列表了。
免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。