如何只用 MySQL 遍历 Table 树

How to Loop through a Table Tree with only MySQL

要知道的事情:

问题:

我将如何遍历此 MySQL 语句? (下面给出声明)

下面的语句现在有效,我还有进一步的 CASE WHEN 来添加它,但现在我正在尝试解决整个事情中最令人困惑的部分。

我需要遍历 MySQL 语句(或找到另一种方法来编写相同的内容),直到到达树的底部。为了说明我正在尝试做的事情:

假设我需要从顶部开始获取整棵树的下线。这意味着我必须为下面的每个人 运行 这个 MySQL 声明。

在我们目前的设置中,我像这样将他们上面的人的 ID 存储在记录中,要跟随记录向下,我必须给它上线 ID 和 return 具有该上线 ID 的所有记录,return 所有即时下线。

+---------+-------------+------+
| ID      | Upline ID   | Name |
+---------+-------------+------+
| 745753  | 654-64645-3 | John |
| 098678  | 916-59172-1 | Jill |
| 543272  | 866-99573-8 | Fred |
| 634543  | 126-97939-3 | Dean |
| 923461  | 734-84628-5 | Bill |
| 861345  | 643-01957-0 | Cris |
+---------+-------------+------+

这意味着对于集合中的每一行 returned,我必须按照 MySQL 语句分别沿着每个记录树向下,并对每一行 returned 执行相同的操作,导致 MySQL 语句成倍增加,直到,当我 运行 该记录的语句时,什么都没有 returned,所以我到达了下线的末尾。

无需进一步等待,这里是声明(我在 WHERE 子句中将其放在顶部 ID 的第一人称以开始声明):

    SELECT wn_writing_number_cstm.title_c, 
    wn_writing_number.`name`, 
    preps_contracted_reps.first_name, 
    preps_contracted_reps.last_name, 
    cac_customize_agent_comp_cstm.commission_percentage_c, 
    wn_writing_number_cstm.id_c
FROM wn_writing_number 
     LEFT OUTER JOIN wn_writing_number_cac_customize_agent_comp_1_c ON wn_writing_number_cac_customize_agent_comp_1_c.wn_writing946b_number_ida = wn_writing_number.id
     LEFT OUTER JOIN cac_customize_agent_comp ON wn_writing_number_cac_customize_agent_comp_1_c.wn_writing3148nt_comp_idb = cac_customize_agent_comp.id
     LEFT OUTER JOIN cac_customize_agent_comp_cstm ON cac_customize_agent_comp.id = cac_customize_agent_comp_cstm.id_c
     LEFT OUTER JOIN aos_products_cac_customize_agent_comp_1_c ON cac_customize_agent_comp_cstm.id_c = aos_products_cac_customize_agent_comp_1_c.aos_produca2b8nt_comp_idb
     LEFT OUTER JOIN preps_contracted_reps_wn_writing_number_1_c ON preps_contracted_reps_wn_writing_number_1_c.preps_contracted_reps_wn_writing_number_1wn_writing_number_idb = wn_writing_number.id
     LEFT OUTER JOIN preps_contracted_reps ON preps_contracted_reps_wn_writing_number_1_c.preps_cont9effed_reps_ida = preps_contracted_reps.id
     LEFT OUTER JOIN wn_writing_number_cstm ON wn_writing_number_cstm.id_c = wn_writing_number.id
WHERE wn_writing_number_cstm.wn_writing_number_id_c = '53506bbe-008f-577c-2114-576b32e0ad11'

这里有一个查询生成器图来帮助说明这个模型:

最后,这就是这条语句实际上 returns,我需要再次 运行 这条语句两次,每行一次,每个行的 ID我的 WHERE 子句中的那些记录:

+---------+-------------+------------+-------------------------------------+
| title_c | name        | first_name | last_name | percent_c | id_c        |
+---------+-------------+------------+-------------------------------------+
| A       | MP-AB0682-16| Andrea     | Donald    | 10        | 823462345   |
| GA      | RO-RM4619-16| Ronald     | Yeller    | 12        | 632811634   |
+---------+-------------+------------+-----------+-----------+-------------+

如需进一步说明,请发表评论。谢谢!

一个半伪代码答案来阐明我的方法(抱歉,没有时间获得更精确的解决方案,并且不要经常使用语法来准确记住它而无需查找):

DECLARE lastInsertCount INT;
DECLARE lastLayer INT;
CREATE TABLE `temp`
(
   `layer` int,
   [fields you want and parent's identifier]
);

INSERT INTO `temp`(`layer`, fields you want...)
SELECT 0, fields you want...
FROM theTable
WHERE [is "root" result]
;
SET lastLayer := 0;

SET lastInsertCount := 1;
LayerLoop: WHILE lastInsertCount > 0

  INSERT INTO `temp`(`layer`, fields you want...)
  SELECT lastLayer + 1, fields you want...
  FROM theTable
  WHERE parent_id IN (SELECT id FROM `temp` WHERE layer = lastLayer)
  ;

  SET lastInsertCount := ROW_COUNT();
  SET lastLayer := lastLayer + 1;

END WHILE LayerLoop;

SELECT fields you want...
FROM `temp`
;

DROP TABLE `temp`;

编辑:如果你允许 "cycles" 在树中,这将使其不是树(但我不得不担心它在坏数据中),你可以避免那些导致你无限循环的添加

AND id NOT IN (SELECT id FROM `temp`)

到 where 子句。