Mysql程序,反复返回分层数据

时间:2017-09-27 20:23:09

标签: mysql stored-procedures procedure

我有用户表,其中包含以下字段

用户     user_id INT
    parent_user_id INT
    一个INT
    b INT

我想创建一个返回给定parent_user_id

的所有子节点的过程

这里有我的

DROP PROCEDURE IF EXISTS read_user_tree;
DELIMITER //
CREATE PROCEDURE read_user_tree(IN input_data INT) NOT DETERMINISTIC
BEGIN

    SET @id = input_data;
    myLoop: loop
        SELECT `user_id`, `a`, `b` into @id, @a, @b FROM `user` WHERE parent_user_id = @id;
        if  
            @id is null
        then
            leave myLoop; 
        end if;
           SELECT `user_id`, `a`, `b` FROM `user` WHERE user_id = @a
           union
           SELECT `user_id`, `a`, `b` FROM `user` WHERE user_id = @b;

    end loop myLoop; 

END //
DELIMITER ;

当我运行此PROCEDURE时,我得到的是随机结果而不是树数据

编辑1:

我尝试将数据添加到临时表中但收到错误“#1172 - 结果由多行组成”

DROP PROCEDURE IF EXISTS read_user_tree;
DELIMITER //
CREATE PROCEDURE read_user_tree(IN input_data INT) NOT DETERMINISTIC
BEGIN

    SET @id = input_data;

 CREATE TEMPORARY TABLE tmp_user_data (
    `user_id` int(11) NOT NULL, 
    `a` int(11) NOT NULL, 
    `b` int(11) NOT NULL, 
    `parent_user_id` int(11) NOT NULL
  ) ENGINE=MEMORY DEFAULT CHARSET=latin1;

  myLoop: loop
        SELECT `user_id`, `a`, `b` into @id, @a, @b FROM `user` WHERE parent_user_id = @id;
        if
            @id is null
        then
            leave myLoop;
        end if;
        insert into tmp_user_data (`user_id`, `a`, `b`, `parent_user_id`)
        SELECT `user_id`, `a`, `b`, `parent_user_id` FROM `user` WHERE user_id = @a;
        insert into tmp_user_data (`user_id`, `a`, `b`, `parent_user_id`)
        SELECT `user_id`, `a`, `b`, `parent_user_id` FROM `user` WHERE user_id = @b;

    end loop myLoop; 

    select * from tmp_user_data;

END //
 DELIMITER ;

编辑2:

在添加第二个tmp表以用作队列后,我得到了期望结果

DROP PROCEDURE IF EXISTS read_user_tree;
DELIMITER //
CREATE PROCEDURE read_user_tree(IN input_data INT) NOT DETERMINISTIC
BEGIN

    SET @id = input_data;

 CREATE TEMPORARY TABLE tmp_user_data (
    `user_id` int(11) NOT NULL, 
    `a` int(11) , 
    `b` int(11) , 
    `parent_user_id` int(11)
  ) ENGINE=MEMORY DEFAULT CHARSET=latin1;

 CREATE TEMPORARY TABLE tmp_user_level (
    `user_id` int(11) NOT NULL
  ) ENGINE=MEMORY DEFAULT CHARSET=latin1;


  insert into tmp_user_level select user_id from `user` WHERE parent_user_id = @id;
  myLoop: loop
        select user_id into @cur from tmp_user_level LIMIT 1;
        select FOUND_ROWS() into @cnt;
        if
            @cnt = 0
        then
            leave myLoop;
        end if;
        SELECT `user_id`, `a`, `b`, `parent_user_id` into @user_id, @a, @b, @parent_user_id FROM `user` WHERE user_id = @cur; 
        insert into tmp_user_data (`user_id`, `a`, `b`, `parent_user_id`) values( @user_id, @a, @b, @parent_user_id);
        delete from tmp_user_level where user_id = @cur;
         if
           @a is not null
        then
            insert into tmp_user_level (user_id) values(@a);
        end if;

        if
           @b is not null
        then
            insert into tmp_user_level (user_id) values(@b);
        end if;

    end loop myLoop; 
    select * from tmp_user_data;


END //
 DELIMITER ;

1 个答案:

答案 0 :(得分:0)

从记忆中走出来,如果错误就道歉。但是您可能需要创建临时表并在循环内插入查询结果。这就是我以前的做法。

CREATE TEMPORARY TABLE results LIKE `user`;
...
<loop>
...
INSERT INTO results (user, a, b)
   SELECT ... UNION SELECT ... ;
...
</loop>
SELECT * FROM results;
DROP TEMPORARY TABLE results;

您必须拥有创建临时表的权限;