通过事先等价的MySQL连接

所有,

我有一个表中的三个字段定义了MySQL数据库版本5.0中存在的父子关系。 表名是tb_Tree,它有以下数据:

Table Name: tb_Tree Id | ParentId | Name -------------------- 1 | 0 | Fruits 2 | 0 | Vegetables 3 | 1 | Apple 4 | 1 | Orange 5 | 2 | Cabbage 6 | 2 | Eggplant 

如果指定了ParentId,我该如何编写一个Query来获取所有的孩子。 请注意,给出的表格条目仅仅是样本数据,并且可以有更多的行。 Oracle有一个“CONNECT BY PRIOR”子句,但是我没有发现类似于MySQL的东西。 任何人都可以请指教?

谢谢

MySQL不支持recursion查询,所以你必须这样做:

  1. selectParentID = X的行,其中X是您的根。
  2. 收集(1)中的Id值。
  3. 从(2)中为每个Id重复(1)。
  4. 继续手工recursion,直到find所有的叶节点。

如果你知道一个最大的深度,那么你可以将自己的表join(使用LEFT OUTER JOINs)到最大可能的深度,然后清理NULL。

您也可以将您的树形表示更改为嵌套集合 。

你也可以看看这个有趣的博客,它展示了如何在mysql中获得类似的结果

http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/

这是一个古老的线程,但因为我在另一个论坛中得到了问题,所以我想在这里添加它。 对于这种情况,我创build了一个硬编码来处理特定情况的存储过程。 这当然有一些缺点,因为不是所有的用户都可以随意创build存储过程,但是。

考虑下面的节点和子表:

 CREATE TABLE nodes ( parent INT, child INT ); INSERT INTO nodes VALUES ( 5, 2), ( 5, 3), (18, 11), (18, 7), (17, 9), (17, 8), (26, 13), (26, 1), (26,12), (15, 10), (15, 5), (38, 15), (38, 17), (38, 6), (NULL, 38), (NULL, 26), (NULL, 18); 

有了这个表,下面的存储过程将计算一个结果集,它由所有提供节点的人组成:

 delimiter $$ CREATE PROCEDURE find_parts(seed INT) BEGIN -- Temporary storage DROP TABLE IF EXISTS _result; CREATE TEMPORARY TABLE _result (node INT PRIMARY KEY); -- Seeding INSERT INTO _result VALUES (seed); -- Iteration DROP TABLE IF EXISTS _tmp; CREATE TEMPORARY TABLE _tmp LIKE _result; REPEAT TRUNCATE TABLE _tmp; INSERT INTO _tmp SELECT child AS node FROM _result JOIN nodes ON node = parent; INSERT IGNORE INTO _result SELECT node FROM _tmp; UNTIL ROW_COUNT() = 0 END REPEAT; DROP TABLE _tmp; SELECT * FROM _result; END $$ delimiter ; 

下面的select列出了所有植物和他们的关parentid 4级(当然你可以延长关卡):

 select id, name, parentid ,(select parentid from tb_tree where id=t.parentid) parentid2 ,(select parentid from tb_tree where id=(select parentid from tb_tree where id=t.parentid)) parentid3 ,(select parentid from tb_tree where id=(select parentid from tb_tree where id=(select parentid from tb_tree where id=t.parentid))) parentid4 from tb_tree t 

然后你可以使用这个查询来获得最终的结果。 例如,你可以通过下面的sql获得“Fruits”的所有子项:

 select id ,name from ( select id, name, parentid ,(select parentid from tb_tree where id=t.parentid) parentid2 ,(select parentid from tb_tree where id=(select parentid from tb_tree where id=t.parentid)) parentid3 ,(select parentid from tb_tree where id=(select parentid from tb_tree where id=(select parentid from tb_tree where id=t.parentid))) parentid4 from tb_tree t) tt where ifnull(parentid4,0)=1 or ifnull(parentid3,0)=1 or ifnull(parentid2,0)=1 or ifnull(parentid,0)=1 

下面的存储过程sorting一个表,该表的行具有对前一个的引用。 注意第一步我将行复制到临时表中 – 这些行匹配一些条件。 在我的情况下,这些行属于同一个线性(在GPS导航中使用的道路)。 业务领域并不重要。 就我而言,我正在sorting属于同一条道路的细分市场

DROP程序如果存在orderLocations; DELIMITER //

CREATE PROCEDURE orderLocations(_full_linear_code VARCHAR(11))BEGIN

 DECLARE _code VARCHAR(11); DECLARE _id INT(4); DECLARE _count INT(4); DECLARE _pos INT(4); DROP TEMPORARY TABLE IF EXISTS temp_sort; CREATE TEMPORARY TABLE temp_sort ( id INT(4) PRIMARY KEY, pos INT(4), code VARCHAR(11), prev_code VARCHAR(11) ); -- copy all records to sort into temp table - this way sorting would go all in memory INSERT INTO temp_sort SELECT id, -- this is primary key of original table NULL, -- this is position that still to be calculated full_tmc_code, -- this is a column that references sorted by negative_offset -- this is a reference to the previous record (will be blank for the first) FROM tmc_file_location WHERE linear_full_tmc_code = _full_linear_code; -- this is how many records we have to sort / update position SELECT count(*) FROM temp_sort INTO _count; -- first position index SET _pos = 1; -- pick first record that has no prior record SELECT code, id FROM temp_sort l WHERE prev_code IS NULL INTO _code, _id; -- update position of the first record UPDATE temp_sort SET pos = _pos WHERE id = _id; -- all other go by chain link WHILE (_pos < _count) DO SET _pos = _pos +1; SELECT code, id FROM temp_sort WHERE prev_code = _code INTO _code, _id; UPDATE temp_sort SET pos = _pos WHERE id = _id; END WHILE; -- join two tables and return position along with all other fields SELECT t.pos, l.* FROM tmc_file_location l, temp_sort t WHERE t.id = l.id ORDER BY t.pos; END;