探索 MySQL 递归查询,优雅的给树结构分页!

6 篇文章 0 订阅
1 篇文章 0 订阅

一、概述

递归查询是一种在数据库中处理具有层级结构数据的技术。它通过在查询语句中嵌套引用自身,以实现对嵌套数据的查询。递归查询在处理树状结构、父子关系或层级关系的数据时非常有用。

MySQL中,递归查询可以使用WITH RECURSIVE语句来实现。该语句允许我们定义一个递归查询,并在查询中引用自身。

递归查询通常包含两个部分:基础查询递归查询

图片

  • 基础查询是指查询的起始点,它返回递归查询中的初始结果集。

  • 递归查询部分定义了如何从基础查询的结果集中继续查询下一层的数据,直到满足终止条件为止。

注意:MySQL是在8.0才引入的窗口函数功能;属于MySQL8的新特性

二、结构

递归查询通常包含以下几个关键元素:

图片

  • 初始查询Anchor Query):这是递归查询的起点,返回初始结果集。它是递归查询的第一步。

  • 递归查询Recursive Query):这是递归查询的核心部分,它引用自身并定义了如何从上一层的结果集中继续查询下一层的数据。递归查询通常包含一个递归关系,通过引用父节点与子节点之间的关联来构建数据的层级结构。

  • 终止条件Termination Condition):这是递归查询的结束条件,用于指定何时停止递归查询。终止条件通常是基于已查询的数据的某种条件或限制。

三、递归查询的执行过程

递归查询的执行过程如下:

图片

  1. 执行初始查询,获取初始结果集。

  2. 将初始结果集作为递归查询的输入,执行递归查询,并将结果集与初始结果集合并。

  3. 重复执行递归查询,直到满足终止条件为止。

四、递归查询的应用场景

递归查询在许多应用场景中都是非常有用的。以下是一些常见的递归查询的应用场景:

图片

注意:以上内容只是递归查询的一些常见应用场景,实际上,递归查询可以适用于任何具有层级或递归结构的数据。通过合理地设计和应用递归查询,可以更轻松地处理复杂的数据关系和层次结构,提供更高效和灵活的数据访问和分析能力。

五、一个案例演示递归查询

为了更好的认识递归查询,这里使用一个简单的组织架构来演示一下递归查询是怎么实现的。

5.1 创建一个组织架构表

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 在这个组织架构表里面插入一些数据

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 使用递归查询分页查看我们的组织架构

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 NULL条件查找根节点,选择了根节点的组织信息(org_id, org_name, parent_id, org_level)

  • 然后,使用UNION ALLINNER 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进行排序。通过LIMITOFFSET可以设置每页的条目数量和偏移量,实现分页查询。

六、总结

递归查询在处理父子结构、树状结构或层级关系的数据时非常有用。它允许我们轻松地查询所有层级的数据,无论层级有多深。递归查询还可以用于处理分页查询、路径查询、层级计算等各种复杂的查询需求。

需要注意的是,递归查询可能会占用较多的系统资源,并且在处理大型数据集时可能会导致性能问题。因此,在使用递归查询时,需要谨慎设计和优化查询,以确保查询的效率和性能。

最后说一句(求关注!别白嫖!)

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。

关注公众号:woniuxgg,在公众号中回复:笔记  就可以获得蜗牛为你精心准备的java实战语雀笔记,回复面试、开发手册、有超赞的粉丝福利!

  • 31
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
/** * 根据等级查询类目树 * * @param level * @return */ @Override public List queryCategoryTree(Integer level) { //查询当前级别下类目 List list = categoryDAO.list(level); //组装好的类目树,返回前端 List categoryTree = new ArrayList(); //所有类目 List allDTOList = new ArrayList(); if (CollectionUtils.isEmpty(list)) { return categoryTree; } for (CategoryDO categoryDO : list) { allDTOList.add(new CategoryTreeDTO().convertDOToDTO(categoryDO)); } //当前等级类目 categoryTree = allDTOList.stream().filter(dto -> level.equals(dto.getLevel())).collect(Collectors.toList()); for (CategoryTreeDTO categoryTreeDTO : categoryTree) { //组装类目为树结构 assembleTree(categoryTreeDTO, allDTOList,Constants.CATEGORY_MAX_LEVEL - level); } return categoryTree; } /** * 组装树 * * @param categoryTreeDTO * @param allList * @param remainRecursionCount 剩余递归次数 * @return */ public CategoryTreeDTO assembleTree(CategoryTreeDTO categoryTreeDTO, List allList, int remainRecursionCount) { remainRecursionCount--; //最大递归次数不超过Constants.CATEGORY_MAX_LEVEL-level次,防止坏数据死循环 if(remainRecursionCount < 0){ return categoryTreeDTO; } String categoryCode = categoryTreeDTO.getCategoryCode(); Integer level = categoryTreeDTO.getLevel(); //到达最后等级树返回 if (Constants.CATEGORY_MAX_LEVEL == level) { return categoryTreeDTO; } //子类目 List child = allList.stream().filter(a -> categoryCode.equals(a.getParentCode())).collect(Collectors.toList()); if (null == child) { return categoryTreeDTO; } categoryTreeDTO.setChildren(child); //组装子类目 for (CategoryTreeDTO dto : child) { assembleTree(dto, allList,remainRecursionCount); } return categoryTreeDTO; }
MySQL递归查询树结构是指在MySQL数据库中,通过使用递归查询语句来查询树形结构的数据树形结构是一种常见的数据结构,例如组织架构、分类目录等都可以表示为树形结构。 在MySQL中,可以使用递归查询语句来查询树形结构的数据递归查询语句使用了WITH RECURSIVE关键字来定义递归查询,并通过递归调用自身来实现对树形结构的遍历。 下面是一个示例,假设有一个名为categories的表,其中包含了id、name和parent_id字段,用于表示分类目录的树形结构: ``` CREATE TABLE categories ( id INT PRIMARY KEY, name VARCHAR(50), parent_id INT ); INSERT INTO categories (id, name, parent_id) VALUES (1, '电子产品', NULL), (2, '手机', 1), (3, '电脑', 1), (4, '苹果手机', 2), (5, '小米手机', 2), (6, '华为手机', 2), (7, '苹果电脑', 3), (8, '联想电脑', 3); ``` 要查询整个分类目录的树形结构,可以使用以下递归查询语句: ``` WITH RECURSIVE category_tree AS ( SELECT id, name, parent_id, 0 AS level FROM categories WHERE parent_id IS NULL UNION ALL SELECT c.id, c.name, c.parent_id, ct.level + 1 FROM categories c INNER JOIN category_tree ct ON c.parent_id = ct.id ) SELECT * FROM category_tree; ``` 这个查询语句中,首先定义了一个递归查询表category_tree,初始查询是根节点(parent_id为NULL的节点),然后通过UNION ALL和JOIN操作递归查询子节点,直到查询完整个树形结构。 通过执行以上查询语句,可以得到如下结果: ``` id | name | parent_id | level --+--+--+------ 1 | 电子产品 | NULL | 0 2 | 手机 | 1 | 1 3 | 电脑 | 1 | 1 4 | 苹果手机 | 2 | 2 5 | 小米手机 | 2 | 2 6 | 华为手机 | 2 | 2 7 | 苹果电脑 | 3 | 2 8 | 联想电脑 | 3 | 2 ``` 这样就可以通过递归查询语句来获取整个树形结构的数据

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值