在项目中会遇到同一个表中保存着父子关系的数据,最常见的就是处理树形结构资源。下面举个简单的例子,先看一下表:
CREATE TABLE `resource` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(11) NOT NULL DEFAULT '0',
`name` varchar(20) COLLATE utf8mb4_bin NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB
然后我们再插入一些数据:
INSERT INTO `resource`(`id`, `parent_id`, `name`) VALUES (8, 0, 'root');
INSERT INTO `resource`(`id`, `parent_id`, `name`) VALUES (9, 8, 'level 1 item 1');
INSERT INTO `resource`(`id`, `parent_id`, `name`) VALUES (10, 8, 'level 1 item 2');
INSERT INTO `resource`(`id`, `parent_id`, `name`) VALUES (11, 9, 'level 2 item 11');
INSERT INTO `resource`(`id`, `parent_id`, `name`) VALUES (12, 9, 'level 2 item 12');
INSERT INTO `resource`(`id`, `parent_id`, `name`) VALUES (13, 10, 'level 2 item21');
INSERT INTO `resource`(`id`, `parent_id`, `name`) VALUES (14, 10, 'level 2 item 22');
INSERT INTO `resource`(`id`, `parent_id`, `name`) VALUES (15, 0, 'root 1');
INSERT INTO `resource`(`id`, `parent_id`, `name`) VALUES (16, 15, 'child for root 1');
INSERT INTO `resource`(`id`, `parent_id`, `name`) VALUES (17, 15, 'child for root 1');
插入数据之后数据在数据库中就是这样的:
在mysql中无法使用像oracle中的start with....connect by的语法,所以我们只能使用函数去查询,函数里面进行逐级查询:
drop FUNCTION if EXISTS queryTree;
CREATE FUNCTION queryTree(rootId int)
RETURNS VARCHAR(4000)
BEGIN
DECLARE temp VARCHAR(200);
DECLARE children VARCHAR(4000);
SET temp = CAST(rootId as CHAR);
WHILE temp is not null DO
set children = concat_ws(',',children,temp);
select GROUP_CONCAT(id) into temp FROM resource WHERE FIND_IN_SET(parent_id,temp) > 0;
END WHILE;
return children;
END
这里我们定义的函数queryTree,在内部定义了2个变量 temp 和 children,temp用于存储当前查询的子集id,children用于存储所有的子集。
接下来我们分析一下执行流程(假设我们查询的rootId = 8):
1. 先把我们要查询的跟节点id赋值给temp,此时temp= ‘8’,children=''。
2. 这个时候temp不为null,所以会进入到循环,首先会进行字符串连接,执行set children = concat_ws(',',children,temp);
之后,此时children=‘8’;
3.重新赋值temp,FIND_IN_SET(parent_id,temp)
查询的就是在表中所有parent_id为8的数据,此时temp='9,10'.(在下一次循环的时候,temp的值就会被追加到children中去)。
4.因为temp不为null,所以会重复2,3。
现在我们来执行一下这个函数看看返回的结果:
select queryTree(8);
对比一下上面的数据库截图,是否正好是所有的树结构id。