MySQL 如何从自引用表中获取层级数据

MySQL 如何从自引用表中获取层级数据

MySQL是一款常用的开源关系数据库管理系统,支持多种操作系统,如Linux、Unix和Windows。本文将介绍如何从自引用表中获取层级数据。即,自我参考表是一个表格,其中一些记录通过指向同一表中其他记录的外键来形成分层结构。这样的表通常用于表示组织架构、产品分类等层级结构。

阅读更多:MySQL 教程

问题描述

假设我们有一个 名为Org的表,其中包含以下列:
– id: 组织机构id
– name: 组织机构名称
– parent_id: 父级组织机构id

其中,parent_id引用了同一表中另一个记录的id,表示它的父级组织机构。我们的任务是获取给定组织机构的所有子组织机构,以及它们的子孙组织机构,包括它们的名称和id。

我们将使用以下示例Org表格:

CREATE TABLE `Org` (
    `id` INT NOT NULL, 
    `name` VARCHAR(50) NOT NULL, 
    `parent_id` INT NULL, 
    PRIMARY KEY (`id`), 
    FOREIGN KEY (`parent_id`) REFERENCES `Org` (`id`)
);

INSERT INTO Org(id, name, parent_id) VALUES(1, '组织机构1', NULL); 
INSERT INTO Org(id, name, parent_id) VALUES(2, '组织机构2', 1); 
INSERT INTO Org(id, name, parent_id) VALUES(3, '组织机构3', 1); 
INSERT INTO Org(id, name, parent_id) VALUES(4, '组织机构4', 2); 
INSERT INTO Org(id, name, parent_id) VALUES(5, '组织机构5', 2); 
INSERT INTO Org(id, name, parent_id) VALUES(6, '组织机构6', 3); 
INSERT INTO Org(id, name, parent_id) VALUES(7, '组织机构7', 3); 
INSERT INTO Org(id, name, parent_id) VALUES(8, '组织机构8', 4); 
INSERT INTO Org(id, name, parent_id) VALUES(9, '组织机构9', 4); 
INSERT INTO Org(id, name, parent_id) VALUES(10, '组织机构10', 5); 
INSERT INTO Org(id, name, parent_id) VALUES(11, '组织机构11', 5); 
INSERT INTO Org(id, name, parent_id) VALUES(12, '组织机构12', 6); 
INSERT INTO Org(id, name, parent_id) VALUES(13, '组织机构13', 6); 
INSERT INTO Org(id, name, parent_id) VALUES(14, '组织机构14', 7); 
INSERT INTO Org(id, name, parent_id) VALUES(15, '组织机构15', 7); 

解决方案

在进行本教程的其余部分之前,请确保您已经安装并启动来自 http://dev.mysql.com/downloads/ 的MySQL。我们将使用MySQL的递归查询功能来解决这个问题。

1. 查询所有子组织机构

为了找到所有子组织机构,我们可以使用与父组织机构关联的递归查询。

WITH RECURSIVE CTE AS 
(
SELECT id, name, parent_id 
FROM Org 
WHERE id = 1 

UNION ALL 

SELECT c.id, c.name, c.parent_id 
FROM Org AS c JOIN CTE 
ON c.parent_id = CTE.id 
) 
SELECT * 
FROM CTE;

查询的结果为:

+----+-------------+-----------+
| id | name        | parent_id |
+----+-------------+-----------+
|  1 | 组织机构1     |      NULL |
|  2 | 组织机构2     |         1 |
|  4 | 组织机构4     |         2 |
|  8 | 组织机构8     |         4 |
| 9 | 组织机构9     |         4 |
|  5 | 组织机构5     |         2 |
| 10 | 组织机构10   |         5 |
| 11 | 组织机构11   |         5 |
|  3 | 组织机构3     |         1 |
|  6 | 组织机构6     |         3 |
| 12 | 组织机构12   |         6 |
| 13 | 组织机构13   |         6 |
|  7 | 组织机构7     |         3 |
| 14 | 组织机构14   |         7 |
| 15 | 组织机构15   |         7 |
+----+-------------+-----------+

从结果中可以看到所有组织机构都有一个相同的 根节点(id=1)。

2. 查询特定组织机构的所有子组织机构

要查询特定组织机构的所有子组织机构,需要在查询中使用该组织机构的id。例如,如果我们要查询“组织机构5”的所有子组织机构,则可以将上面的查询修改为:

WITH RECURSIVE CTE AS 
(
SELECT id, name, parent_id 
FROM Org 
WHERE id = 5 

UNION ALL 

SELECT c.id, c.name, c.parent_id 
FROM Org AS c JOIN CTE 
ON c.parent_id = CTE.id 
) 
SELECT * 
FROM CTE;

查询的结果为:

+----+------------+-----------+
| id | name       | parent_id |
+----+------------+-----------+
|  5 | 组织机构5    |         2 |
| 10 | 组织机构10  |         5 |
| 11 | 组织机构11  |         5 |
+----+------------+-----------+

从结果中可以看到,“组织机构5”有两个子组织机构:“组织机构10”和“组织机构11”。

3. 查询特定组织机构的所有子孙组织机构

要查询特定组织机构的所有子孙组织机构,需要在查询中使用它的id,并稍微修改查询中的条件。例如,如果我们要查询“组织机构2”的所有子孙组织机构,则可以将上面的查询修改为:

WITH RECURSIVE CTE AS 
(
SELECT id, name, parent_id 
FROM Org 
WHERE id = 2 

UNION ALL 

SELECT c.id, c.name, c.parent_id 
FROM Org AS c JOIN CTE 
ON c.parent_id = CTE.id 
) 
SELECT * 
FROM CTE 
WHERE id != 2;

查询的结果为:

+----+------------+-----------+
| id | name       | parent_id |
+----+------------+-----------+
|  4 | 组织机构4    |         2 |
|  8 | 组织机构8    |         4 |
|  9 | 组织机构9    |         4 |
|  5 | 组织机构5    |         2 |
| 10 | 组织机构10  |         5 |
| 11 | 组织机构11  |         5 |
+----+------------+-----------+

从结果中可以看到,“组织机构2”有四个子孙组织机构:“组织机构4”、“组织机构8”、“组织机构9”和“组织机构5”,以及它们的子孙组织机构。

总结

本文介绍了如何从自引用表中获取层级数据。我们使用MySQL的递归查询功能来查询特定组织机构的所有子组织机构、所有子孙组织机构以及表中的所有数据。希望这个教程能够对你有所帮助。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程