找出mysql中反向层次结构的列表

时间:2013-10-06 13:41:00

标签: mysql sql myisam

想象一下,我有一个表(Mysql myISAM),其中包含子 - >父关系(类别和子类别的多个级别)

+--------+---------+
| id     |parent_id|
+--------+---------+
| 1      |  null   |
| 2      |    1    |
| 3      |    2    |
| 4      |    7    |
| 5      |    1    |
| 6      |    5    |
+--------+---------+

你怎么能找到一些ID的所有孩子,比如查询id 1会输出: 2,5,3,6? (顺序没有重要性)

换句话说,如何在这个parent_link上进行恢复的子查找?

目前,我在php中循环并查询parent_id,然后再次在字符串中连接所有结果,但结果却很慢......

3 个答案:

答案 0 :(得分:1)

好的,感谢Deepak代码,我设法编写了这个,可读性稍差,它接受一个表作为参数,并返回元素的深度。

DELIMITER $$

CREATE PROCEDURE get_children(IN V_KEY INT,IN SOURCETABLE VARCHAR(255))
proc:
BEGIN
  DECLARE vid text;
  DECLARE count int;

  DROP TABLE IF EXISTS `temp_child_nodes`;
  CREATE TEMPORARY TABLE temp_child_nodes(id int, depth int);

  SET vid = V_KEY;
  SET @val = '';
  SET count = 0;

  WHILE (vid is NOT NULL) DO 

      SET @sql = CONCAT("INSERT INTO temp_child_nodes(id,depth) SELECT id,'",count,"' from ",SOURCETABLE," where parent_id IN (",vid,")");
      PREPARE stmt1 FROM @sql;
      EXECUTE stmt1;
      DEALLOCATE PREPARE stmt1;


      SET @tsql = CONCAT("SELECT GROUP_CONCAT(id) INTO @val from ",SOURCETABLE," where parent_id IN (", vid, ")");
      PREPARE stmt2 FROM @tsql;
      EXECUTE stmt2;
      DEALLOCATE PREPARE stmt2;
      SET vid = @val;

      SET count = count + 1;
  END WHILE;

  #output data
  SELECT * from temp_child_nodes; 

END
$$

DELIMITER ;

答案 1 :(得分:0)

以下是您的查询的sqlfiddle演示 http://sqlfiddle.com/#!2/ca90e/6

如果可能有'n'个孩子,那么你需要使用存储过程

答案 2 :(得分:0)

create table my_table(
id int,
parent_id int
);

insert into my_table values
(1,null),
(2,1),
(3,2),
(4,7),
(5,1),
(6,5);

此存储过程将为您提供任何给定ID的所有子项

DELIMITER $$
DROP PROCEDURE IF EXISTS get_children$$

CREATE PROCEDURE get_children(IN V_KEY INT)
proc:
BEGIN
  DECLARE vid text;
declare oid text;
  DECLARE count int;
  CREATE TEMPORARY TABLE temp_child_nodes(
      id int
    );

  SET vid = V_KEY;
  INSERT INTO temp_child_nodes(id) SELECT id from my_table where parent_id = vid;
  SELECT GROUP_CONCAT(concat("'",id,"'")) INTO oid from my_table where parent_id = vid;

  SET vid = oid;
  SET count = 0;
  SET @val = '';
  WHILE (vid is NOT NULL) DO 

      SET @sql = CONCAT("INSERT INTO temp_child_nodes(id) SELECT id from my_table where parent_id IN (",vid,")");
      PREPARE stmt1 FROM @sql;
      EXECUTE stmt1;
      DEALLOCATE PREPARE stmt1;

      SET @tsql = CONCAT("SELECT GROUP_CONCAT(id) INTO @val from my_table where parent_id IN (", vid, ")");
      PREPARE stmt2 FROM @tsql;
      EXECUTE stmt2;
      DEALLOCATE PREPARE stmt2;
      SET vid = @val;
      SET count = count + 1;
  END WHILE;
  #SELECT count;
  SELECT * from temp_child_nodes; 
  #SELECT oid;
END
$$

DELIMITER ;

CALL get_children(1);

mysql> CALL get_children(1);
+------+
| id   |
+------+
|    2 |
|    5 |
|    3 |
|    6 |
+------+
4 rows in set (0.22 sec)

Query OK, 0 rows affected (0.22 sec)