MySQL 树形结构 根据指定节点 获取其所有叶子节点
背景说明
需求:MySQL树形结构, 根据指定的节点,获取其下属的所有叶子节点。
叶子节点:如果一个节点下不再有子节点,则为叶子节点。
问题分析
1、可以使用类似Java这种面向对象的语言,对节点集合进行逻辑处理,获取叶子节点。
2、直接自定义MySQL函数 getLeafNodeList,通过两层while循环,实现对指定节点的所有叶子节点进行查询。
功能实现
1、创建数据表
1)表结构截图如下(此处简单建一张表 t_tree,id主键自增,uuid表示本节点,parent_uuid表示父节点):

2)建表语句如下:
/*
Navicat Premium Data Transfer Source Server : localhost
Source Server Type : MySQL
Source Server Version : 50724
Source Host : localhost:3306
Source Schema : test_db Target Server Type : MySQL
Target Server Version : 50724
File Encoding : 65001 Date: 07/05/2019 21:04:57
*/ SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0; -- ----------------------------
-- Table structure for t_tree
-- ----------------------------
DROP TABLE IF EXISTS `t_tree`;
CREATE TABLE `t_tree` (
`id` int(20) NOT NULL AUTO_INCREMENT,
`uuid` int(20) NULL DEFAULT NULL,
`parent_uuid` int(20) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 15 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ----------------------------
-- Records of t_tree
-- ----------------------------
INSERT INTO `t_tree` VALUES (1, 1, 0);
INSERT INTO `t_tree` VALUES (2, 2, 0);
INSERT INTO `t_tree` VALUES (3, 3, 0);
INSERT INTO `t_tree` VALUES (4, 11, 1);
INSERT INTO `t_tree` VALUES (5, 12, 1);
INSERT INTO `t_tree` VALUES (6, 21, 2);
INSERT INTO `t_tree` VALUES (7, 22, 2);
INSERT INTO `t_tree` VALUES (8, 211, 21);
INSERT INTO `t_tree` VALUES (9, 221, 22);
INSERT INTO `t_tree` VALUES (10, 222, 22);
INSERT INTO `t_tree` VALUES (11, 223, 22);
INSERT INTO `t_tree` VALUES (12, 2231, 223);
INSERT INTO `t_tree` VALUES (13, 2232, 223);
INSERT INTO `t_tree` VALUES (14, 0, ); SET FOREIGN_KEY_CHECKS = 1;
3)表数据结构如下:

4)树形结构如下图:

2、编写查询叶子节点函数 getLeafNodeList,如下:
CREATE DEFINER=`root`@`localhost` FUNCTION `getLeafNodeList`(`nodeId` int) RETURNS varchar(1000) CHARSET utf8
BEGIN
DECLARE leafNodeList VARCHAR(1000); # 返回叶子节点结果集
DECLARE tempChild VARCHAR(1000); # 临时存放子节点
DECLARE count int; # 计算节点下是否有节点,count = 0 表示为叶子节点
DECLARE tempLeaf VARCHAR(1000); # 临时存放可能的叶子节点
DECLARE leafNode VARCHAR(1000); # 存放叶子节点 SET leafNodeList = '';
SET tempChild = CAST(nodeId as CHAR); # 将int类型转换为String类型 WHILE tempChild is not null DO # 外层循环,用于查询节点下所有的子节点
SET tempLeaf = tempChild; # 临时存放节点,用于内层循环判定是否为叶子节点,避免影响外层循环使用 tempChild
WHILE LENGTH(tempLeaf) > 0 DO # 内层循环,用于判断外层查询到的子节点是否为叶子节点
SET leafNode = SUBSTRING_INDEX(tempLeaf, ',', 1); # 假定逗号分隔的第一个为叶子节点
select count(uuid) INTO count from t_tree where parent_uuid = leafNode; # 查询该节点下是否有子节点
IF count = 0 THEN
SET leafNodeList = CONCAT(leafNodeList, ',', leafNode); # 如果该节点下没有子节点,则认为是叶子节点,存入到返回结果中
END IF;
SET tempLeaf = SUBSTRING(tempLeaf, LENGTH(leafNode) + 2); # 将第一个节点截取掉,继续识别剩余的节点
END WHILE; SELECT GROUP_CONCAT(uuid) INTO tempChild FROM t_tree where FIND_IN_SET(parent_uuid, tempChild) > 0; # 查询节点下所有子节点
END WHILE; RETURN SUBSTRING(leafNodeList, 2); # 将返回结果进行处理,截取掉结果集前面的逗号
END
其中,用到了很多MySQL的系统函数,如:CAST,SUBSTRING,SUBSTRING_INDEX,CONCAT,GROUP_CONCAT,FIND_IN_SET。
3、调用函数
select getLeafNodeList(1) as leafNodeList;
0)查询节点0 的叶子节点:从树形图可以看到,应该是 3,11,12,211,221,222,2231,2232

1)查询节点1 的叶子节点:从树形图可以看到,应该是 11,12

2)查询节点2 的叶子节点:从树形图可以看到,应该是 211,221,222,2231,2232

3)查询节点3 的叶子节点:从树形图可以看到,应该是 3

问题总结
该问题核心点是内层循环查找叶子节点,按照上面的表数据和截图,阅读SQL函数,很好理解。
希望能帮到需要帮助的同行,谢谢。
PS:
1)如果需要 根据指定的节点,获取其下属的所有子节点(包含路径上的所有枝干节点和叶子节点)
请参考本人的另一篇博文:https://www.cnblogs.com/miracle-luna/p/10828592.html
2)如果需要 根据指定节点,获取其所有父节点序列
请参考本人的另一篇博文:https://www.cnblogs.com/miracle-luna/p/10878224.html
3)如果需要 根据指定节点,获取其所在全路径节点序列
请参考本人的另一篇博文:https://www.cnblogs.com/miracle-luna/p/10878366.html
MySQL 树形结构 根据指定节点 获取其所有叶子节点的更多相关文章
- MySQL 树形结构 根据指定节点 获取其所在全路径节点序列
背景说明 需求:MySQL树形结构, 根据指定的节点,获取其所在全路径节点序列. 问题分析 1.可以使用类似Java这种面向对象的语言,对节点集合进行逻辑处理,获取全路径节点序列. 2.直接自定义My ...
- MySQL 树形结构 根据指定节点 获取其所有父节点序列
背景说明 需求:MySQL树形结构, 根据指定的节点,获取其所有父节点序列. 问题分析 1.可以使用类似Java这种面向对象的语言,对节点集合进行逻辑处理,获取父节点. 2.直接自定义MySQL函数 ...
- MySQL 树形结构 根据指定节点 获取其下属的所有子节点(包含路径上的枝干节点和叶子节点)
背景说明 需求:MySQL树形结构, 根据指定的节点,获取其下属的所有子节点(包含路径上的枝干节点和叶子节点) 枝干节点:如果一个节点下还有子节点,则为枝干节点. 叶子节点:如果一个节点下不再有子节点 ...
- 获取所有树叶子节点 注册添加事件 if ($(node).tree('isLeaf', node.target)) 是否叶子节点
//获取所有树叶子节点 注册添加事件 if ($(node).tree('isLeaf', node.target)) 是否叶子节点 $(function () { $('.easyui-tree') ...
- MySQL树形结构的数据库表设计和查询
1.邻接表(Adjacency List) 实例:现在有一个要存储一下公司的人员结构,大致层次结构如下: 那么怎么存储这个结构?并且要获取以下信息: 1.查询小天的直接上司. 2.查询老宋管理下的直属 ...
- JQuery 各节点获取函数:父节点,子节点,兄弟节点
jQuery.parent(expr) //找父元素 jQuery.parents(expr) //找到所有祖先元素,不限于父元素 jQuery.children ...
- 求二叉树第K层的节点个数+求二叉树叶子节点的个数
size_t _FindLeafSize(Node* root) //求二叉树叶子节点的个数 { //static size_t count = 0; if ...
- 六:二叉树中第k层节点个数与二叉树叶子节点个数
二叉树中第k层节点个数 递归解法: (1)假设二叉树为空或者k<1返回0 (2)假设二叉树不为空而且k==1.返回1 (3)假设二叉树不为空且k>1,返回左子树中k-1层的节点个数与右子树 ...
- mysql树形结构递归查询
之前一直用的是Oracle,对于树形查询可以使用start with ... connect by ' connect by id = prior parent_id; 没错,这是Oracle所支持的 ...
随机推荐
- Pythonic Code In Several Lines
1. Fibonacci Series def Fib(n): if n == 1 or n == 2: return 1; else: return Fib(n - 1) + Fib(n - 2) ...
- excel匹配相应条件 自动填充数据
=VLOOKUP(A6&B6,IF({1,0},Sheet3!$A$3:$A$505&Sheet3!$B$3:$C$505,Sheet3!$Q$3:$Q$505),2,0) =VLOO ...
- json校验失败的原因
如下原因会造成JSON校验失败,而且会让你不知道为什么失败 JSON字符串里的非数字型键值没有双引号 JSON中存在\t这样的制表符,看起来和空格一样,但是就是因为它的存在校验不通过.去掉就能过了. ...
- Kendo UI for jQuery使用教程:操作系统/jQuery支持等
[Kendo UI for jQuery最新试用版下载] Kendo UI目前最新提供Kendo UI for jQuery.Kendo UI for Angular.Kendo UI Support ...
- 关于css阴影和浮动
盒子阴影box-shadow box-shadow:0 0 1px #000 inset; 水平 垂直 模糊 颜色 : [1] inset代表框内阴影,不加inset代表框外阴影 [2]第1个 ...
- 说一说你对HTML5语义化的理解
本题地址:https://github.com/YvetteLau/Step-By-Step/issues/8 语义化意味着顾名思义,HTML5的语义化指的是合理使用语义化的标签来创建页面结构,如he ...
- vs2017 2019 下载更新慢的解决方法
国庆期间 下载的速度只有20多kb. 1.去掉网络适配器里面的 ip6勾选. 2.修改电脑的自动dns, 修改为1.1.1.1 , 修改为8.8.8.8 更快. 记得禁用再启用网络: dns为1. ...
- C# 扩展方法——序列化与反序列化
其他扩展方法详见:https://www.cnblogs.com/zhuanjiao/p/12060937.html 主要是是对日期格式的处理 using Newtonsoft.Json; using ...
- CSS层定位——固定定位,相对定位,绝对定位
主要写关于层定位的相关知识 ㈠定位概述 ⑴像图像软件中的图层一样可以对每一个layer能够精确定位操作 ⑵层定位的position属性决定了当前的一个网页元素,可以叠加到另一个网页元素上面,那么我们把 ...
- 上传文件夹 vue
ASP.NET上传文件用FileUpLoad就可以,但是对文件夹的操作却不能用FileUpLoad来实现. 下面这个示例便是使用ASP.NET来实现上传文件夹并对文件夹进行压缩以及解压. ASP.NE ...