【问题标题】:Select tree path in MySQL table在 MySQL 表中选择树路径
【发布时间】:2017-10-29 04:20:57
【问题描述】:

我有一个这样的 MySQL 表:

| CategoryId |          Name | CategoryParentId |
|------------|---------------|------------------|
|          0 |  Tech Support |           (null) |
|          1 | Configuration |                0 |
|          2 |     Questions |                1 |
|          3 |         Sales |           (null) |
|          4 |     Questions |                3 |
|          5 |         Other |           (null) |

这是我在查询 ID 2 时想要的输出(例如):

技术支持/配置/问题

如何在不进行多次连接的情况下做到这一点?

Fiddle

编辑:不确定是否是最好的方法,但我通过创建一个函数来解决:

DELIMITER $$

CREATE FUNCTION get_full_tree (CategoryId int) RETURNS VARCHAR(200)

BEGIN
SET @CategoryParentId = (SELECT CategoryParentId FROM category c WHERE c.CategoryId = CategoryId);
SET @Tree = (SELECT Name FROM category c WHERE c.CategoryId = CategoryId);
WHILE (@CategoryParentId IS NOT NULL) DO
    SET @ParentName = (SELECT Name FROM category c WHERE c.CategoryId = @CategoryParentId);
    SET @Tree = CONCAT(@ParentName, '/', @Tree);
    SET @CategoryParentId = (SELECT CategoryParentId FROM category c WHERE c.CategoryId = @CategoryParentId);
END WHILE;
RETURN @Tree;
END $$
DELIMITER ;

我现在可以做这个查询了:

SELECT CategoryId, get_full_tree(CategoryId) FROM category

【问题讨论】:

  • 不确定是否可以在一行中完成。您可以从 MYTABLE 中选择名称,其中 CATEGORYID

标签: mysql recursion tree hierarchical


【解决方案1】:

您可以创建一个新表,将其命名为hierarchy(可能是一个更好的名称),我们将在其中存储一个类别的所有祖先。

CREATE TABLE `hierarchy` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `parent` int(11) NOT NULL,
  `child` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

例如,在这种情况下,QuestionsID->2 我们将有以下条目:

id  parent     child
====================            
6     0         2
7     1         2
8     2         2

对于整个示例,表格的内容是:

id       parent     child
===========================
1           0           0
2           3           3
3           5           5
4           0           1
5           1           1
6           0           2
7           1           2
8           2           2
9           3           4
10          4           4

现在,当您想要检索节点的整个祖先时,请执行以下查询:

select name from category where id in (select parent from hierarchy where child = 2 order by id ASC)

上述查询将返回 Questions (ID->2) 的所有祖先名称,即

name
==================
Tech Support
Configuration
Questions

为了完整起见,下面是category table 的内容

id             Name
============================
0             Tech Support
1             Configuration
2             Questions
3             Sales
4             Questions
5             Other

注意这只是一个想法,我相信您绝对可以在此基础上构建更优雅的解决方案。

【讨论】:

    【解决方案2】:

    如果您使用的是 MySQL 8 或更高版本,则可以使用通用表表达式进行递归查询。查询如下

    WITH RECURSIVE CategoryPath (CategoryId, Name, path) AS
    (
      SELECT CategoryId, Name, Name as path
        FROM category
        WHERE CategoryParentId IS NULL
      UNION ALL
      SELECT c.CategoryId, c.Name, CONCAT(cp.path, ' / ', c.Name)
        FROM CategoryPath AS cp JOIN category AS c
          ON cp.CategoryId = c.CategoryParentId 
    )
    SELECT * FROM CategoryPath ORDER BY path;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-02
      • 2020-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-26
      相关资源
      最近更新 更多