草庐IT

mysql - 递归循环 - 父/子树

coder 2023-10-13 原文

我正在尝试递归循环并返回所有具有 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]

程序一(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 次,所以我的代码中一定有一个错误没有停止递归,我相信与 done 有关 myloop: 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 - 递归循环 - 父/子树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44378439/

有关mysql - 递归循环 - 父/子树的更多相关文章

  1. ruby - 树顶语法无限循环 - 2

    我脑子里浮现出一些关于一种新编程语言的想法,所以我想我会尝试实现它。一位friend建议我尝试使用Treetop(Rubygem)来创建一个解析器。Treetop的文档很少,我以前从未做过这种事情。我的解析器表现得好像有一个无限循环,但没有堆栈跟踪;事实证明很难追踪到。有人可以指出入门级解析/AST指南的方向吗?我真的需要一些列出规则、常见用法等的东西来使用像Treetop这样的工具。我的语法分析器在GitHub上,以防有人希望帮助我改进它。class{initialize=lambda(name){receiver.name=name}greet=lambda{IO.puts("He

  2. ruby-on-rails - 在 Ruby 中循环遍历多个数组 - 2

    我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代

  3. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  4. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  5. ruby - Ruby 中的闭包和 for 循环 - 2

    我是Ruby的新手,有些闭包逻辑让我感到困惑。考虑这段代码:array=[]foriin(1..5)array[5,5,5,5,5]这对我来说很有意义,因为i被绑定(bind)在循环之外,所以每次循环都会捕获相同的变量。使用每个block可以解决这个问题对我来说也很有意义:array=[](1..5).each{|i|array[1,2,3,4,5]...因为现在每次通过时都单独声明i。但现在我迷路了:为什么我不能通过引入一个中间变量来修复它?array=[]foriin1..5j=iarray[5,5,5,5,5]因为j每次循环都是新的,我认为每次循环都会捕获不同的变量。例如,这绝对

  6. ruby-on-rails - 无法安装 mysql2 0.3.14 gem - 2

    我看到其他人也遇到过类似的问题,但没有一个解决方案对我有用。0.3.14gem与其他gem文件一起存在。我已经完全按照此处指示完成了所有操作:https://github.com/brianmario/mysql2.我仍然得到以下信息。我不知道为什么安装程序指示它找不到include目录,因为我已经检查过它存在。thread.h文件存在,但不在ruby​​目录中。相反,它在这里:C:\RailsInstaller\DevKit\lib\perl5\5.8\msys\CORE\我正在运行Windows7并尝试在Aptana3中构建我的Rails项目。我的Ruby是1.9.3。$gemin

  7. ruby - 递归地将所有数字字符串转换为 Ruby 哈希中的整数 - 2

    我有一个随机大小的散列,它可能有类似"100"的值,我想将其转换为整数。我知道我可以使用value.to_iifvalue.to_i.to_s==value来做到这一点,但我不确定我将如何在我的散列中递归地做到这一点,考虑到一个值可以是一个字符串,或一个数组(哈希或字符串),或另一个哈希。 最佳答案 这是一个非常简单的递归实现(尽管必须同时处理数组和散列会增加一些技巧)。deffixnumifyobjifobj.respond_to?:to_i#IfwecancastittoaFixnum,doit.obj.to_ielsifobj

  8. ruby - 如何使用 ruby​​ mysql2 执行事务 - 2

    我已经开始使用mysql2gem。我试图弄清楚一些基本的事情——其中之一是如何明确地执行事务(对于批处理操作,比如多个INSERT/UPDATE查询)。在旧的ruby-mysql中,这是我的方法:client=Mysql.real_connect(...)inserts=["INSERTINTO...","UPDATE..WHEREid=..",#etc]client.autocommit(false)inserts.eachdo|ins|beginclient.query(ins)rescue#handleerrorsorabortentirelyendendclient.commi

  9. Ruby:标准递归模式 - 2

    我经常迷上ruby​​的一件事是递归模式。例如,假设我有一个数组,它可能包含无限深度的数组作为元素。所以,例如:my_array=[1,[2,3,[4,5,[6,7]]]]我想创建一个方法,可以将数组展平为[1,2,3,4,5,6,7]。我知道.flatten可以完成这项工作,但这个问题是作为我经常遇到的递归问题的一个例子-因此我试图找到一个更可重用的解决方案。简而言之-我猜这种事情有一个标准模式,但我想不出任何特别优雅的东西。任何想法表示赞赏 最佳答案 递归是一种方法,它不依赖于语言。您在编写算法时要考虑两种情况:再次调用函数的情

  10. ruby - 为什么我用递归得到 "stack level too deep"? - 2

    我有这个ruby代码:defget_sumnreturn0ifn似乎正在为999之前的值工作。当我尝试9999时,它给了我这个:stackleveltoodeep(SystemStackError)所以,我添加了这个:RubyVM::InstructionSequence.compile_option={:tailcall_optimization=>true,:trace_instruction=>false}但什么也没发生。我的ruby版本是:ruby1.9.3p392(2013-02-22revision39386)[x86_64-darwin12.2.1]我还增加了机器的堆栈大

随机推荐