我有一个像这样的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时所需的输出(例如):
技术支持/配置/问题
如何在不进行多次连接的情况下执行此操作?
编辑:不确定这是否是最好的方法,但我通过创建一个函数来解决:
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
答案 0 :(得分: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;
例如,在这种情况下Questions
,即 ID-> 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
表
id Name
============================
0 Tech Support
1 Configuration
2 Questions
3 Sales
4 Questions
5 Other
N.B。这只是一个想法,我相信你绝对可以在它上面构建更优雅的解决方案。
答案 1 :(得分:1)
如果您使用的是MySQL 8或更高版本,则可以使用Common Table Expressions进行递归查询。查询如下
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;