mysql – 递归循环 – 父/子树
作者:互联网
我试图以递归方式循环并返回所有具有9的根元素的child_id.
结构:
+-- 9
| +-- 8
| +-- 17
| +-- 33
| +-- 18
| +-- 22
| +-- 11
| +-- 4
父子链接表:(表名:elements_children)
+----+-----------+----------+
| id | parent_id | child_id |
+----+-----------+----------+
| 1 | 9 | 8 |
| 2 | 8 | 17 |
| 3 | 8 | 33 |
| 4 | 8 | 18 |
| 5 | 9 | 22 |
| 6 | 22 | 11 |
| 7 | 22 | 4 |
| 8 | 3 | 5 |
+----+-----------+----------+
期望的产出 – [8,17,33,18,22,11,4]
程序1(getChildren):
BEGIN
-- CREATE TEMP TABLE
DROP TABLE IF EXISTS total_children;
CREATE TEMPORARY TABLE total_children(
id INT(11) NOT NULL auto_increment PRIMARY KEY,
child_id VARCHAR(255)
);
-- CALL TO PROCEDURE 2
CALL getNodes(rootNode);
-- SELECT child_id's FROM the temp table, then drop the table
SELECT child_id FROM total_children;
DROP TABLE total_children;
END
过程2(getNodes):
BEGIN
-- VARIABLES
DECLARE done BOOLEAN DEFAULT FALSE;
DECLARE childNode VARCHAR(255);
-- CURSOR1
DECLARE cur1 CURSOR FOR SELECT child_id FROM elements_children WHERE parent_id = parentNode;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
-- START LOOP
myloop:LOOP
FETCH cur1 INTO childNode;
-- CHECK IF DONE IS TRUE
IF(done) THEN
LEAVE myloop;
END IF;
-- APPEND TO TOTAL
INSERT INTO total_children(child_id) SELECT childNode;
-- RECURSIVE
CALL getNodes(childNode);
END LOOP myloop;
-- END LOOP
-- END CURSOR1
CLOSE cur1;
END
I’m getting error: recursion limit exceeded 200
我将递归限制设置为200,并且我知道该过程不应该递归200次,因此我的代码中必须存在错误,而不是停止递归,我相信与myloop中的done变量有关:LOOP .
问题:为什么我的过程会产生此递归错误?
解决方法:
我认为以下存储过程将产生您要求的结果.我设置了一个表,并用你问题中的数据填充它:
DROP TABLE IF EXISTS `parent_child`;
CREATE TABLE `parent_child` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'Primary Key',
`parent_id` INT(10) UNSIGNED NOT NULL,
`child_id` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_parent_child_parent_id` (`parent_id`)
)
ENGINE=MyISAM
AUTO_INCREMENT=1
DEFAULT CHARSET=utf8
COLLATE=utf8_unicode_ci
COMMENT '';
INSERT INTO `parent_child`
(`id`,`parent_id`,`child_id`)
VALUES
('1','9','8'),
('2','8','17'),
('3','8','33'),
('4','8','18'),
('5','9','22'),
('6','22','11'),
('7','22','4'),
('8','3','5');
然后我创建了一个程序来逐步获取孩子,直到没有任何剩下来.
DROP PROCEDURE GetChildren;
DELIMITER //
CREATE PROCEDURE GetChildren(root_id INT)
BEGIN
SET @list = root_id;
SET @new_list = root_id;
SET @maxDepth = 4;
SET @depth = 0;
WHILE (@new_list <> "" AND @depth < @maxDepth) DO
SELECT @new_list as `new_list_before`,@list as `whole_list_before`;
SET @depth = @depth + 1;
SET @querystr = CONCAT("SELECT GROUP_CONCAT(`child_id`) as `children` INTO @c FROM `parent_child` WHERE `parent_id` in (?) AND (NOT (`child_id` IN (?)));");
PREPARE stmt1 FROM @querystr;
EXECUTE stmt1 USING @new_list,@list;
IF @c <> "" THEN
SET @list = CONCAT(@list,",",@c);
END IF;
SET @new_list = @c;
SELECT @new_list as `new_list`,@list as `whole_list`;
DEALLOCATE PREPARE stmt1;
END WHILE;
SELECT @list;
END //
DELIMITER ;
最后,这是如何调用root id为9:
CALL GetChildren(9);
这会产生:
@list:
9,8,22,17,33,18
作为参考,这是执行的选择之一:
SELECT GROUP_CONCAT(`child_id`) as `children`
FROM `parent_child`
WHERE `parent_id` in (9,8,22) AND (NOT `child_id` IN (9,8,22))
GROUP BY `parent_id`;
标签:mysql,recursive-query,b-tree 来源: https://codeday.me/bug/20190710/1427746.html