目录

前言

1.准备分类数据

2.递归原理

3.实现

4.结合mybatis查询

总结


前言

相信大家在处理业务的时候经常会遇到分类数据,当面对这种情况时该如何处理呢?在这里我使用了两种方式解决:一种使用sql递归的方式,另一种是java代码方式处理(下一期)。


一、SQL递归

1.准备分类数据

代码如下(示例):

DROP TABLE IF EXISTS `course_category`;
CREATE TABLE `course_category`  (`id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键',`name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '分类名称',`label` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '分类标签默认和名称一样',`parentid` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '父结点id(第一级的父节点是0,自关联字段id)',`is_show` tinyint NULL DEFAULT NULL COMMENT '是否显示',`orderby` int NULL DEFAULT NULL COMMENT '排序字段',`is_leaf` tinyint NULL DEFAULT NULL COMMENT '是否叶子',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '课程分类' ROW_FORMAT = DYNAMIC;-- ----------------------------
-- Records of course_category
-- ----------------------------INSERT INTO `course_category` VALUES ('1-3-3', '.NET', '.NET', '1-3', 1, 3, 1);
INSERT INTO `course_category` VALUES ('1-3-4', 'Objective-C', 'Objective-C', '1-3', 1, 4, 1);
INSERT INTO `course_category` VALUES ('1-3-5', 'Go语言', 'Go语言', '1-3', 1, 5, 1);INSERT INTO `course_category` VALUES ('1-4', '数据库', '数据库', '1', 1, 4, 0);
INSERT INTO `course_category` VALUES ('1-4-1', 'Oracle', 'Oracle', '1-4', 1, 1, 1);
INSERT INTO `course_category` VALUES ('1-4-2', 'MySQL', 'MySQL', '1-4', 1, 2, 1);
INSERT INTO `course_category` VALUES ('1-4-3', 'SQL Server', 'SQL Server', '1-4', 1, 3, 1);
INSERT INTO `course_category` VALUES ('1-4-4', 'DB2', 'DB2', '1-4', 1, 4, 1);
INSERT INTO `course_category` VALUES ('1-4-5', 'NoSQL', 'NoSQL', '1-4', 1, 5, 1);
INSERT INTO `course_category` VALUES ('1', '根结点', '根结点', '0', 1, 1, 0);
INSERT INTO `course_category` VALUES ('1-1', '前端开发', '前端开发', '1', 1, 1, 0);
INSERT INTO `course_category` VALUES ('1-1-1', 'HTML/CSS', 'HTML/CSS', '1-1', 1, 1, 1);
INSERT INTO `course_category` VALUES ('1-1-2', 'JavaScript', 'JavaScript', '1-1', 1, 2, 1);
INSERT INTO `course_category` VALUES ('1-1-3', 'jQuery', 'jQuery', '1-1', 1, 3, 1);
INSERT INTO `course_category` VALUES ('1-1-4', 'ExtJS', 'ExtJS', '1-1', 1, 4, 1);
INSERT INTO `course_category` VALUES ('1-1-5', 'AngularJS', 'AngularJS', '1-1', 1, 5, 1);INSERT INTO `course_category` VALUES ('1-2', '移动开发', '移动开发', '1', 1, 2, 0);
INSERT INTO `course_category` VALUES ('1-2-1', '微信开发', '微信开发', '1-2', 1, 1, 1);
INSERT INTO `course_category` VALUES ('1-2-2', 'iOS', 'iOS', '1-2', 1, 2, 1);
INSERT INTO `course_category` VALUES ('1-2-3', '手游开发', '手游开发', '1-2', 1, 3, 1);
INSERT INTO `course_category` VALUES ('1-2-4', 'Swift', 'Swift', '1-2', 1, 4, 1);
INSERT INTO `course_category` VALUES ('1-2-5', 'Android', 'Android', '1-2', 1, 5, 1);INSERT INTO `course_category` VALUES ('1-3', '编程开发', '编程开发', '1', 1, 3, 0);
INSERT INTO `course_category` VALUES ('1-3-1', 'C/C++', 'C/C++', '1-3', 1, 1, 1);
INSERT INTO `course_category` VALUES ('1-3-2', 'Java', 'Java', '1-3', 1, 2, 1);

 表图如下所示:

2.递归原理

要实现sql递归查询,首先要明白其原理。

递归查询原理:SQL Server中的递归查询是通过CTE(表表达式)来实现。至少包含两个子查询,第一个查询为定点成员(种子查询),种子查询只是作为一个根查询,用于递归的定位;第二个查询被称为递归查询, 这两个子查询可以通过 UNION、UNION ALL或UNION DISTINCT 连接在一起。

注意RECURSIVE 关键字只在MySQL8+版本生效。种子查询只会执行一次,并得到初始的数据作为根子集,而递归查询没有显式的递归终止条件,只有当第二个递归查询重复执行(实现递归)直到没有新的行产生,返回空结果集或是超出了递归次数的最大限制时才停止递归。最终将所有的结果集都查询出来,这对于深层查询(如具有父子关系的查询)是非常有用的。

优点:效率高,大量数据集下,速度比程序的查询快。

SQL递归的常见形式:

WITH RECURSIVE CTE AS (

SELECT column1,column2... FROM tablename WHERE conditions

UNION ALL

SELECT column1,column2... FROM tablename

INNER JOIN CTE ON conditions

)

3.实现

sql如下:

with recursive t1 as (
select * from course_category p where id= "1"union allselect t.* from course_category t inner join t1 on t1.id = t.parentid)select * from t1 order by t1.id, t1.orderby

查询结果如下:

4.结合mybatis查询

引入依赖如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.12.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>testdemo</artifactId><version>0.0.1-SNAPSHOT</version><name>testdemo</name><description>testdemo</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.1</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency></dependencies><build><resources><resource><!-- xml放在java目录下--><directory>src/main/java</directory><includes><include>**/*.xml</include></includes></resource></resources><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

yml配置:

spring:datasource:username: rootpassword: rooturl: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghaidriver-class-name: com.mysql.cj.jdbc.Driver
#  注意这里的配置 我是把mapper映射放在java目录下 才这样写的
mybatis-plus:mapper-locations: com/example/testdemo/dao/*.xml

目录结构如下所示:

Course实体类:

@Data
@TableName(value = "course_category")
public class Course implements Serializable {@TableField(value = "id")private String id;private String name;private String label;@TableField(value = "parentid")private String parentId;@TableField(value = "is_show")private Integer isShow;private Integer orderby;@TableField(value = "is_leaf")private Integer isLeaf;@TableField(exist = false)List<Course> courseList;
}

CourseMapper映射类:

@Mapper
public interface CourseMapper extends BaseMapper<Course> {List<Course> selectTreeByRootId(String id);
}

CourseMapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.testdemo.mapper.CourseMapper"><select id="selectTreeByRootId" resultType="com.example.testdemo.entity.Course" parameterType="string">with recursive t1 as (select * from course_category p where id= #{id}union allselect t.* from course_category t inner join t1 on t1.id = t.parentid)select * from t1 order by t1.id, t1.orderby</select>
</mapper>

因为返回数据并不满足分类格式,所以 最后再把数据封装进Crouse就行 ,封装操作如下:

CourseServiceImpl类:
    @AutowiredCourseMapper courseMapper;@Overridepublic  List<Course> selectTreeNode(String id){List<Course> courseList =  courseMapper.selectTreeByRootId(id);List<Course> categoryTreeDtos = new ArrayList<>();HashMap<String, Course> mapTemp = new HashMap<>();courseList.stream().forEach(item->{mapTemp.put(item.getId(),item);//只将根节点的下级节点放入listif(item.getParentId().equals("1")){categoryTreeDtos.add(item);}Course fatherCourse = mapTemp.get(item.getParentId());if(fatherCourse!=null){if(fatherCourse.getCourseList() ==null){fatherCourse.setCourseList(new ArrayList<Course>());}//向节点的下级节点list加入节点fatherCourse.getCourseList().add(item);}});return categoryTreeDtos;}

测试:

    @AutowiredCourseService courseService;@Testvoid context() {List<Course> courseList = courseService.selectTreeNode("1");System.out.println(courseList);}

结果如图遍成功完成:


总结

感谢大家的观看

此文章只是尝试练习递归查分类数据,新手上路,大家多多关照。

SQL递归查询树型分类数据相关推荐

  1. SQL读取树型所有下级或所有上级

    在编程或构建中,可能会遇到常常需要根据树型某个节点,读取其所有上级或所有下级的情况.然后绑定到树型部件显示. 在Oracle中,可以用start with ... connect by prior . ...

  2. mysql 递归查询树型结构_MySQL递归查询所有子节点,树形结构查询

    --表结构 CREATE TABLE `address` ( `id` int(11) NOT NULL AUTO_INCREMENT, `code_value` varchar(32) DEFAUL ...

  3. 利用ajax,巧妙的sql语句组合,轻松做出不错的树型菜单

    我们的某个项目中,在设计报表时候,考虑到做报表的树型分类,同时考虑到分类下存在子分类和报表并存,使用原有项目中jtree功能已经达不到这要求,因此,考虑蛮久,还是自己写一个吧. 注意: 前提需知: 本 ...

  4. 使用SQL2005 递归查询结合Row_Number()实现完全SQL端树排序

    使用SQL2005 递归查询结合Row_Number()实现完全SQL端树排序 在实际应用中,我们经常需要用到树型结构功能,数据库结构一般如下 即用一个ParentID来标识该节点从属关系.为了最终生 ...

  5. 无限极分类php简单,创建无限极分类树型结构的简单方法

    先上效果图 顶级分类其实就是一级分类,二级分类也叫作一级分类的子分类,在这个基础上,子分类还可以拥有子分类,这样就构成了无限极分类. 接下来看具体实现的代码: 一.在控制器中按字段查询,查询出所有分类 ...

  6. 【唠叨两句】如何将一张树型结构的Excel表格中的数据导入到多张数据库表中...

    小弟昨天遇到一个相对比较棘手的问题,就像标题说的那样.如何将一张树型结构的Excel表格中的数据导入到多张数据库表中,在现实中实际是七张数据库表,这七张表之间有着有着相对比较复杂的主外键关系,对于我这 ...

  7. 数据中心网络架构 — 传统数据中心网络 — 胖树型三层网络架构

    目录 文章目录 目录 胖树型(Fat-Tree)网络架构 Fat-Tree 是一种无带宽收敛的网络架构 Fat-Tree 的网络拓扑 Fat-Tree 的缺点 胖树型(Fat-Tree)网络架构 为了 ...

  8. 数据中心网络架构 — 传统数据中心网络 — 传统树型三层网络架构

    目录 文章目录 目录 数据中心组网架构 传统三层网络架构 核心层(Core Layer) 汇聚层(Aggregation Layer) 接入层(Access Layer) 三层网络架构的设计原则 三层 ...

  9. azure云数据库_Azure SQL数据库中的高级数据安全性–数据发现和分类

    azure云数据库 Azure SQL supports in building and managing wide range of SQL databases, tools, frameworks ...

最新文章

  1. 一文了解Python常见的序列化操作
  2. Docker、kubernetes、微服务、SpringBoot/Cloud...好乱!到底要不要学?
  3. boost::math::relative_difference相关用法的测试程序
  4. AgileConfig - 轻量级配置中心1.2.0发布,全新的UI
  5. 《Effective Java》读书笔记 Item 1:考虑静态工厂方法,而不是构造器
  6. 桥接模式和路由模式区别_联通创维光猫DT541-CSF改桥接模式方法
  7. CSS3 多列布局的跨列
  8. python房屋租赁系统的设计与实现_基于ssh的房屋租赁系统的设计与实现(含源文件)...
  9. antd vue form 手动校验_vue测试模板与jsonSchema自动生成elment组件
  10. JUC总览,来自汪文君整理
  11. 电气防火限流式保护器及其过电流故障检测方法
  12. iOS版本关于微信分享后出现的“未验证应用”
  13. 怒怼外媒,为中国正名,这个《流浪地球》捧红的犹太小哥太励志了
  14. 批量缩小多张图片尺寸,保持图片清晰无损
  15. BLE 技术(八)--- BLE MESH 各层报文是如何设计的(上)?
  16. 计算机 北航 在线作业,北航计算机组成原理在线作业
  17. C语言输入一个日期,计算这一天是周几
  18. android 恢复出厂设置 代码,android恢复出厂设置以及系统升级流程
  19. $ 8 : gets函数与puts函数
  20. Vue错误03:Property or method “xxx“ is not defined on the instance but referenced during render.

热门文章

  1. Pynput模块的学习与创新,基于python的操作录制脚本
  2. 分享| 5个常见小程序营销线上玩法
  3. sen2cor工具箱操作说明
  4. Excel自动转曲线图的时PHP,Excel折线图随着数据的插入动态变化,掌握此技能的人不足1﹪!...
  5. FFmpeg添加x265/hevc编码器支持
  6. 粗糙集理论应用的实例
  7. 内存泄漏问题该如何解决-面试学习笔记
  8. linux 挂载fat32格式u盘
  9. 可折叠手机喂肥了黄牛,但柔性屏的未来从来不止手机
  10. 与MySQL相识的第二天