背景说明
需求:MySQL树形结构, 根据指定的节点,获取其下属的所有子节点(包含路径上的枝干节点和叶子节点)
枝干节点:如果一个节点下还有子节点,则为枝干节点。
叶子节点:如果一个节点下不再有子节点,则为叶子节点。
问题分析
1、可以使用类似Java这种面向对象的语言,对节点集合进行逻辑处理,获取所有子节点。
2、直接自定义MySQL函数 getChildList,通过一层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、编写查询叶子节点函数 getChildList,如下:
CREATE DEFINER=`root`@`localhost` FUNCTION `getChildList`(`nodeId` int) RETURNS varchar(1000) CHARSET utf8 BEGIN DECLARE childList VARCHAR(1000); # 返回叶子节点结果集 DECLARE tempChild VARCHAR(1000); # 临时存放子节点 SET childList = ''; SET tempChild = CAST(nodeId as CHAR); # 将int类型转换为String WHILE tempChild is not null DO # 循环,用于查询节点下所有的子节点 SET childList = CONCAT(childList, ',', tempChild); # 存入到返回结果中 SELECT GROUP_CONCAT(uuid) INTO tempChild FROM t_tree where FIND_IN_SET(parent_uuid, tempChild) > 0; # 查询节点下所有子节点 END WHILE; RETURN SUBSTRING(childList, 2); # 将返回结果处理,截取掉结果集前面的逗号 END
其中,用到了几个MySQL的系统函数,如:CAST,CONCAT,GROUP_CONCAT,FIND_IN_SET。
3、调用函数
select getChildList(1) as childList;
0)查询节点0 的所有子节点:从树形图可以看到,应该是 0,1,2,3,11,12,21,22,211,221,222,223,2231,2232
1)查询节点1 的所有子节点:从树形图可以看到,应该是 1,11,12
2)查询节点2 的所有子节点:从树形图可以看到,应该是 2,21,22,211,221,222,223,2231,2232
3)查询节点3 的所有子节点:从树形图可以看到,应该是 3
问题总结
该问题核心点是循环遍历查找子节点,按照上面的表数据和截图,阅读SQL函数,很好理解。
希望能帮到需要帮助的同行,谢谢。
PS:
1)如果需要 根据指定的节点,获取其下属的所有叶子节点(只包含叶子节点)。
请参考本人的另一篇博文:https://www.cnblogs.com/miracle-luna/p/10828476.html
2)如果需要 根据指定节点,获取其所有父节点序列
请参考本人的另一篇博文:https://www.cnblogs.com/miracle-luna/p/10878224.html
3)如果需要 根据指定节点,获取其所在全路径节点序列
请参考本人的另一篇博文:https://www.cnblogs.com/miracle-luna/p/10878366.html