(注意 Solarflare 建议我以错误的方式使用此递归,请在最后的编辑中查看来自父母的孩子。)
这是我能想到的最快的方法,假设每个孩子只有一个父母,我希望它是正确的。 请注意,我将表名称更改为agentsZ,因为开头有一个drop命令,如果在没有Z的情况下运行,它将清除原始表。这样做的原因是存储过程将运行开箱即用,前提是您将表名称更改为“代理”,并将数据列名称替换为您需要的列的实际名称(星号不起作用)。
原始代码:
# DROP TABLE IF EXISTS agentsZ;
CREATE TABLE agentsZ (id TINYINT UNSIGNED PRIMARY KEY, upline_id TINYINT UNSIGNED, `data` CHAR(8));
INSERT INTO agentsZ
VALUES (1, 4, 'A'),
(2, 3, 'B'),
(5, 8, 'C'),
(6, 7, 'D'),
(4, 9, 'E'),
(3, 9, 'F'),
(9, 12, 'G'),
(8, 11, 'H'),
(7, 10, 'I'),
(12, 13, 'J'),
(11, 14, 'K'),
(10, 14, 'L');
DELIMITER $
DROP PROCEDURE IF EXISTS getParents$
CREATE PROCEDURE getParents(in_id INT)
BEGIN
SET @VUplineID := in_id;
SELECT id, @VUplineID := upline_id upline_id, `data` FROM agentsZ WHERE id = @VUplineID;
END$
DELIMITER ;
CALL getParents(1);
测试代码:
mysql> DROP TABLE IF EXISTS agentsZ;
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql>
mysql> CREATE TABLE agentsZ (id TINYINT UNSIGNED PRIMARY KEY, upline_id TINYINT UNSIGNED, `data` CHAR(8));
Query OK, 0 rows affected (0.06 sec)
mysql>
mysql> INSERT INTO agentsZ
-> VALUES (1, 4, 'A'),
-> (2, 3, 'B'),
-> (5, 8, 'C'),
-> (6, 7, 'D'),
-> (4, 9, 'E'),
-> (3, 9, 'F'),
-> (9, 12, 'G'),
-> (8, 11, 'H'),
-> (7, 10, 'I'),
-> (12, 13, 'J'),
-> (11, 14, 'K'),
-> (10, 14, 'L');
Query OK, 12 rows affected (0.02 sec)
Records: 12 Duplicates: 0 Warnings: 0
mysql>
mysql> DELIMITER $
mysql>
mysql> DROP PROCEDURE IF EXISTS getParents$
Query OK, 0 rows affected (0.02 sec)
mysql>
mysql> CREATE PROCEDURE getParents(in_id INT)
-> BEGIN
->
-> SET @VUplineID := in_id;
-> SELECT id, @VUplineID := upline_id upline_id, `data` FROM agentsZ WHERE id = @VUplineID;
->
-> END$
Query OK, 0 rows affected (0.00 sec)
mysql>
mysql> DELIMITER ;
mysql>
mysql> CALL getParents(1);
+----+-----------+------+
| id | upline_id | data |
+----+-----------+------+
| 1 | 4 | A |
| 4 | 9 | E |
| 9 | 12 | G |
| 12 | 13 | J |
+----+-----------+------+
4 rows in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
稍微不那么优雅,但在这里走另一条路是另一个功能:
DELIMITER $
DROP PROCEDURE IF EXISTS getChildren$
CREATE PROCEDURE getChildren(in_id INT)
BEGIN
SET @VBeforeRows := -1;
SET @VAfterRows := 0;
SET @VDownLineIDRegex := CONCAT('^', in_id, '$');
WHILE @VAfterRows != @VBeforeRows DO
SET @VBeforeRows := @VAfterRows;
DROP TEMPORARY TABLE IF EXISTS ZResults;
CREATE TEMPORARY TABLE ZResults
SELECT id, upline_id, IF(@VDownLineIDRegex REGEXP CONCAT('\|\^', id, '\$'), @VLoop := FALSE, @VDownLineIDRegex := CONCAT(@VDownLineIDRegex, '|^', id, '$')) idRegex, `data` FROM agentsZ WHERE upline_id REGEXP @VDownLineIDRegex;
SELECT COUNT(*) INTO @VAfterRows FROM ZResults;
END WHILE;
SELECT id, upline_id, `data` FROM ZResults;
END$
DELIMITER ;
CALL getChildren(14);
这是我执行时输出的副本:
mysql> DROP TABLE IF EXISTS agentsZ;
Query OK, 0 rows affected (0.02 sec)
mysql>
mysql> CREATE TABLE agentsZ (id TINYINT UNSIGNED PRIMARY KEY, upline_id TINYINT UNSIGNED, `data` CHAR(8));
Query OK, 0 rows affected (0.04 sec)
mysql>
mysql> INSERT INTO agentsZ
-> VALUES (1, 4, 'A'),
-> (2, 3, 'B'),
-> (5, 8, 'C'),
-> (6, 7, 'D'),
-> (4, 9, 'E'),
-> (3, 9, 'F'),
-> (9, 12, 'G'),
-> (8, 11, 'H'),
-> (7, 10, 'I'),
-> (12, 13, 'J'),
-> (11, 14, 'K'),
-> (10, 14, 'L');
Query OK, 12 rows affected (0.02 sec)
Records: 12 Duplicates: 0 Warnings: 0
mysql>
mysql> DELIMITER $
mysql>
mysql> DROP PROCEDURE IF EXISTS getChildren$
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql>
mysql> CREATE PROCEDURE getChildren(in_id INT)
-> BEGIN
->
-> SET @VBeforeRows := -1;
-> SET @VAfterRows := 0;
-> SET @VDownLineIDRegex := CONCAT('^', in_id, '$');
->
-> WHILE @VAfterRows != @VBeforeRows DO
->
-> SET @VBeforeRows := @VAfterRows;
->
-> DROP TEMPORARY TABLE IF EXISTS ZResults;
->
-> CREATE TEMPORARY TABLE ZResults
-> SELECT id, upline_id, IF(@VDownLineIDRegex REGEXP CONCAT('\|\^', id, '\$'), @VLoop := FALSE, @VDownLineIDRegex := CONCAT(@VDownLineIDRegex, '|^', id, '$')) idRegex, `data` FROM agentsZ WHERE upline_id REGEXP @VDownLineIDRegex;
->
-> SELECT COUNT(*) INTO @VAfterRows FROM ZResults;
->
-> END WHILE;
->
-> SELECT id, upline_id, `data` FROM ZResults;
->
-> END$
Query OK, 0 rows affected (0.01 sec)
mysql>
mysql> DELIMITER ;
mysql>
mysql> CALL getChildren(14);
+----+-----------+------+
| id | upline_id | data |
+----+-----------+------+
| 5 | 8 | C |
| 6 | 7 | D |
| 7 | 10 | I |
| 8 | 11 | H |
| 10 | 14 | L |
| 11 | 14 | K |
+----+-----------+------+
6 rows in set (0.13 sec)
Query OK, 0 rows affected (0.13 sec)
问候,
詹姆斯