主要是为每列数据加上一个id链方便查询
- 初始数据
CREATE TABLE node
(
id BIGINT(20) AUTO_INCREMENT NOT NULL,
pId BIGINT(20) NOT NULL,
name VARCHAR(20) NULL,
PRIMARY KEY (id)
);
TRUNCATE node;
INSERT INTO node
VALUES (),(),(),();
INSERT INTO node(id, pId)
VALUES (@id := 5, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1),
(@id := @id + 1, FLOOR(rand() * (@id - 1)) + 1)
;
UPDATE node
SET name= concat('node ', id)
WHERE TRUE;
mysql> SELECT * from node;
+----+------+---------+
| id | pId | name |
+----+------+---------+
| 1 | NULL | node 1 |
| 2 | NULL | node 2 |
| 3 | NULL | node 3 |
| 4 | NULL | node 4 |
| 5 | 1 | node 5 |
| 6 | 5 | node 6 |
| 7 | 3 | node 7 |
| 8 | 2 | node 8 |
| 9 | 1 | node 9 |
| 10 | 4 | node 10 |
| 11 | 1 | node 11 |
| 12 | 11 | node 12 |
| 13 | 8 | node 13 |
| 14 | 3 | node 14 |
| 15 | 4 | node 15 |
| 16 | 8 | node 16 |
| 17 | 13 | node 17 |
| 18 | 9 | node 18 |
| 19 | 1 | node 19 |
| 20 | 15 | node 20 |
| 21 | 12 | node 21 |
| 22 | 16 | node 22 |
| 23 | 20 | node 23 |
| 24 | 4 | node 24 |
| 25 | 7 | node 25 |
| 26 | 19 | node 26 |
| 27 | 25 | node 27 |
| 28 | 12 | node 28 |
| 29 | 12 | node 29 |
| 30 | 23 | node 30 |
| 31 | 18 | node 31 |
| 32 | 22 | node 32 |
| 33 | 20 | node 33 |
+----+------+---------+
33 rows in set (0.00 sec)
- 8.0以下使用函数查询
DELIMITER //
CREATE FUNCTION getIdPath(givenID BIGINT) RETURNS VARCHAR(1024)
DETERMINISTIC
BEGIN
DECLARE idPath VARCHAR(1024);
DECLARE dm CHAR(1);
DECLARE tmpId BIGINT;
SET idPath = '';
SET dm = '';
SET tmpId = givenID;
-- 非根节点需要满足的条件
WHILE tmpId IS NOT NULL
DO
SELECT pId INTO tmpId FROM node WHERE id = tmpId;
-- 非根节点需要满足的条件
IF tmpId IS NOT NULL THEN
SET idPath = CONCAT(idPath, dm, tmpId);
SET dm = ',';
END IF;
END WHILE;
RETURN idPath;
END //
DELIMITER ;
mysql> SELECT *, getIdPath(id) idPath FROM node;
+----+------+---------+------------+
| id | pId | name | idPath |
+----+------+---------+------------+
| 1 | NULL | node 1 | |
| 2 | NULL | node 2 | |
| 3 | NULL | node 3 | |
| 4 | NULL | node 4 | |
| 5 | 1 | node 5 | 1 |
| 6 | 5 | node 6 | 5,1 |
| 7 | 3 | node 7 | 3 |
| 8 | 2 | node 8 | 2 |
| 9 | 1 | node 9 | 1 |
| 10 | 4 | node 10 | 4 |
| 11 | 1 | node 11 | 1 |
| 12 | 11 | node 12 | 11,1 |
| 13 | 8 | node 13 | 8,2 |
| 14 | 3 | node 14 | 3 |
| 15 | 4 | node 15 | 4 |
| 16 | 8 | node 16 | 8,2 |
| 17 | 13 | node 17 | 13,8,2 |
| 18 | 9 | node 18 | 9,1 |
| 19 | 1 | node 19 | 1 |
| 20 | 15 | node 20 | 15,4 |
| 21 | 12 | node 21 | 12,11,1 |
| 22 | 16 | node 22 | 16,8,2 |
| 23 | 20 | node 23 | 20,15,4 |
| 24 | 4 | node 24 | 4 |
| 25 | 7 | node 25 | 7,3 |
| 26 | 19 | node 26 | 19,1 |
| 27 | 25 | node 27 | 25,7,3 |
| 28 | 12 | node 28 | 12,11,1 |
| 29 | 12 | node 29 | 12,11,1 |
| 30 | 23 | node 30 | 23,20,15,4 |
| 31 | 18 | node 31 | 18,9,1 |
| 32 | 22 | node 32 | 22,16,8,2 |
| 33 | 20 | node 33 | 20,15,4 |
+----+------+---------+------------+
33 rows in set (0.00 sec)
- 8.0 使用递归CTE
WITH RECURSIVE nodeTree AS
(
SELECT id, cast(id AS CHAR) idPath
FROM node
-- 根节点满足条件
WHERE pId IS NULL
UNION ALL
SELECT n.id, concat(idPath, ',', cast(n.id AS CHAR))
FROM nodeTree AS nt
JOIN node AS n ON nt.id = n.pId
)
SELECT *
FROM nodeTree
+------+------+---------+---------------+
| id | pId | name | idPath |
+------+------+---------+---------------+
| 1 | NULL | node 1 | 1 |
| 2 | NULL | node 2 | 2 |
| 3 | NULL | node 3 | 3 |
| 4 | NULL | node 4 | 4 |
| 5 | 1 | node 5 | 1,5 |
| 7 | 3 | node 7 | 3,7 |
| 8 | 2 | node 8 | 2,8 |
| 9 | 1 | node 9 | 1,9 |
| 10 | 4 | node 10 | 4,10 |
| 11 | 1 | node 11 | 1,11 |
| 14 | 3 | node 14 | 3,14 |
| 15 | 4 | node 15 | 4,15 |
| 19 | 1 | node 19 | 1,19 |
| 24 | 4 | node 24 | 4,24 |
| 6 | 5 | node 6 | 1,5,6 |
| 12 | 11 | node 12 | 1,11,12 |
| 13 | 8 | node 13 | 2,8,13 |
| 16 | 8 | node 16 | 2,8,16 |
| 18 | 9 | node 18 | 1,9,18 |
| 20 | 15 | node 20 | 4,15,20 |
| 25 | 7 | node 25 | 3,7,25 |
| 26 | 19 | node 26 | 1,19,26 |
| 17 | 13 | node 17 | 2,8,13,17 |
| 21 | 12 | node 21 | 1,11,12,21 |
| 22 | 16 | node 22 | 2,8,16,22 |
| 23 | 20 | node 23 | 4,15,20,23 |
| 27 | 25 | node 27 | 3,7,25,27 |
| 28 | 12 | node 28 | 1,11,12,28 |
| 29 | 12 | node 29 | 1,11,12,29 |
| 31 | 18 | node 31 | 1,9,18,31 |
| 33 | 20 | node 33 | 4,15,20,33 |
| 30 | 23 | node 30 | 4,15,20,23,30 |
| 32 | 22 | node 32 | 2,8,16,22,32 |
+------+------+---------+---------------+
33 rows in set (0.00 sec)