mysql 树查询

主要是为每列数据加上一个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)

你可能感兴趣的:(mysql 树查询)