探索MySQL 递归查询,优雅的给树结构分页
文章摘要
递归查询是处理层级数据的技术,MySQL 8.0及以上版本通过`WITH RECURSIVE`语句实现。它包括初始查询和递归查询两部分,逐层检索数据直到满足终止条件,适用于树状结构、组织架构等场景,但需注意性能优化。
一、概述 ---- 递归查询是一种在数据库中处理具有层级结构数据的技术。它通过在查询语句中嵌套引用自身,以实现对嵌套数据的查询。递归查询在处理树状结构、父子关系或层级关系的数据时非常有用。 在`MySQL`中,递归查询可以使用`WITH RECURSIVE`语句来实现。该语句允许我们定义一个递归查询,并在查询中引用自身。 递归查询通常包含两个部分:**基础查询**和**递归查询**。 ![](https://oss.120120.top/blog/2024/03/15/c12c9707e47f40448437e07995193127.png) * 基础查询是指查询的起始点,它返回递归查询中的初始结果集。 * 递归查询部分定义了如何从基础查询的结果集中继续查询下一层的数据,直到满足终止条件为止。 > 注意:`MySQL`是在**8.0**才引入的窗口函数功能;属于MySQL8的新特性 二、结构 ---- > 递归查询通常包含以下几个关键元素: ![](https://oss.120120.top/blog/2024/03/15/11a1e105efed49f59ed35e064f2485ee.png) * **初始查询**(`Anchor Query`):这是递归查询的起点,返回初始结果集。它是递归查询的第一步。 * **递归查询**(`Recursive Query`):这是递归查询的核心部分,它引用自身并定义了如何从上一层的结果集中继续查询下一层的数据。递归查询通常包含一个递归关系,通过引用父节点与子节点之间的关联来构建数据的层级结构。 * **终止条件**(`Termination Condition`):这是递归查询的结束条件,用于指定何时停止递归查询。终止条件通常是基于已查询的数据的某种条件或限制。 三、递归查询的执行过程 ----------- 递归查询的执行过程如下: ![](https://oss.120120.top/blog/2024/03/15/021f0ce8a7dc45e6bad1be7d0a5671e3.png) > 1. 执行初始查询,获取初始结果集。 > > 2. 将初始结果集作为递归查询的输入,执行递归查询,并将结果集与初始结果集合并。 > > 3. 重复执行递归查询,直到满足终止条件为止。 > 四、递归查询的应用场景 ----------- 递归查询在许多应用场景中都是非常有用的。以下是一些常见的递归查询的应用场景: ![](https://oss.120120.top/blog/2024/03/15/cd5eeceb30074b059514bc165715fea4.png) > 注意:以上内容只是递归查询的一些常见应用场景,实际上,递归查询可以适用于任何具有层级或递归结构的数据。通过合理地设计和应用递归查询,可以更轻松地处理复杂的数据关系和层次结构,提供更高效和灵活的数据访问和分析能力。 五、一个案例演示递归查询 ------------ 为了更好的认识递归查询,这里使用一个简单的组织架构来演示一下递归查询是怎么实现的。 ### 5.1 创建一个组织架构表 ```sql CREATE TABLE `organization` ( `org_id` int NOT NULL COMMENT '主键', `org_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '组织名称', `parent_id` int DEFAULT NULL COMMENT '父组织id', `org_level` int DEFAULT NULL COMMENT '组织级别', PRIMARY KEY (`org_id`), KEY `parent_id` (`parent_id`), CONSTRAINT `organization_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `organization` (`org_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='公司组织架构'; ``` ### 5.2 在这个组织架构表里面插入一些数据 ```sql INSERT INTO `organization`(`org_id`, `org_name`, `parent_id`, `org_level`) VALUES (1, '集团总部', NULL, 1); INSERT INTO `organization`(`org_id`, `org_name`, `parent_id`, `org_level`) VALUES (2, '华北分公司', 1, 2); INSERT INTO `organization`(`org_id`, `org_name`, `parent_id`, `org_level`) VALUES (3, '华南分公司', 1, 2); INSERT INTO `organization`(`org_id`, `org_name`, `parent_id`, `org_level`) VALUES (4, '华北-北京公司', 2, 3); INSERT INTO `organization`(`org_id`, `org_name`, `parent_id`, `org_level`) VALUES (5, '华北-内蒙公司', 2, 3); INSERT INTO `organization`(`org_id`, `org_name`, `parent_id`, `org_level`) VALUES (6, '华南-广州公司', 3, 3); INSERT INTO `organization`(`org_id`, `org_name`, `parent_id`, `org_level`) VALUES (7, '华南-深圳公司', 3, 3); ``` ### 5.3 使用递归查询分页查看我们的组织架构 ```sql WITH RECURSIVE RecursiveOrganization AS ( SELECT org_id, org_name, parent_id, org_level FROM organization WHERE parent_id IS NULL -- 查找根节点 UNION ALL SELECT o.org_id, o.org_name, o.parent_id, o.org_level FROM organization o INNER JOIN RecursiveOrganization ro ON ro.org_id = o.parent_id ) SELECT org_id, org_name, parent_id, org_level FROM RecursiveOrganization ORDER BY org_id LIMIT 2 OFFSET 0; -- 设置每页的条目数量和偏移量 ``` > 解析一下这个`SQL`: > > * 首先,使用`WITH RECURSIVE`子句创建了一个名为`RecursiveOrganization`的递归查询视图。 > > 在初始查询部分,通过`WHERE parent_id IS NUL`L条件查找根节点,选择了根节点的组织信息`(org_id, org_name, parent_id, org_level)`。 > > * 然后,使用`UNION ALL`和`INNER JOIN`将递归查询与`organization`表连接起来,逐级递归获取下级组织的信息。通过`SELECT o.org_id, o.org_name, o.parent_id, o.org_level`选择下级组织的信息,并使用`ON ro.org_id = o.parent_id`指定连接条件。 > > * 最后,从`RecursiveOrganization`视图中选择所需的组织架构数据,并使用`ORDER BY`对结果按`org_id`进行排序。通过`LIMIT`和`OFFSET`可以设置每页的条目数量和偏移量,实现分页查询。 > 六、总结 ---- 递归查询在处理父子结构、树状结构或层级关系的数据时非常有用。它允许我们轻松地查询所有层级的数据,无论层级有多深。递归查询还可以用于处理分页查询、路径查询、层级计算等各种复杂的查询需求。 需要注意的是,递归查询可能会占用较多的系统资源,并且在处理大型数据集时可能会导致性能问题。因此,在使用递归查询时,需要谨慎设计和优化查询,以确保查询的效率和性能。 > 希望本文对您有所帮助。如果有任何错误或建议,请随时指正和提出。 > > 同时,如果您觉得这篇文章有价值,请考虑点赞和收藏。这将激励我进一步改进和创作更多有用的内容。 > > 感谢您的支持和理解! 本文转自 [https://juejin.cn/post/7300174977168441378](https://juejin.cn/post/7300174977168441378),如有侵权,请联系删除。
作者头像
admin
分享技术与生活
打赏作者

评论

暂无评论,快来抢沙发吧~