首页 > 其他分享 >树型表查询

树型表查询

时间:2024-06-12 16:12:07浏览次数:13  
标签:树型表 name 递归 id 查询 节点 select

树型表查询

在开发中,很常见的会用到树形结构,以课程分类结构,其在数据库中的表示如下:

image

通常都是通过 parentId 来描述父亲节点。

查询方式有两种:固定层级查询、递归查询

1、固定层级查询

如果树的层级固定可以使用表的自链接去查询,比如:我们只查询两级课程分类,可以用下边的SQL

SELECT
	a.id 		a_id,
	a.`name` 	a_name,
	b.id 		b_id,
	b.`name` 	b_name,
	c.id 		c_id,
	c.`name` 	c_name
FROM
	course_category a
	INNER JOIN course_category b ON b.parentid = a.id
	INNER JOIN course_category c ON c.parentid = b.id
WHERE
	a.parentid = 0
	AND a.is_show = 1
	AND b.is_show = 1
ORDER BY
	a.orderby,
	b.orderby

存在几级结构就添加几个 inner join 语句。

image

内连接查询就是通过parentid找父节点

1.一次内连接

image

2.两次内连接

image

可以看到,只有在树的层级确定的情况下我才能选择性的去自连接子表,某种意义上来讲这种方法存在弊端,我要是insert进去层级更低的新子节点那我的sql就得改变,从而就造成了一个“动一发而牵全身”的硬编码问题,实在是不够稳妥!

所以该方法只在层级较低查询时简单使用。

2、递归查询

注意:MySQL8.0版本开始支持递归查询,
MySQL递归实现,使用with语法,如下:

    WITH [RECURSIVE] cte_name [(col_name [, col_name] ...)] AS (subquery)
        [, cte_name [(col_name [, col_name] ...)] AS (subquery)] ...
1.向下递归:从根节点开始找子节点

先来看一个简单的Demo

with RECURSIVE t  AS
(
  SELECT 1 as count
  UNION ALL
  SELECT count + 1 FROM t WHERE n < 5
)
SELECT * FROM t;

具体理解如下:

with RECURSIVE t as
1.定义一个递归表 t,所有的操作都是基于该表
select 1 as count
2.初始化递归表 t
union all
3.将步骤4中的操作结果合并到递归表中
select count + 1 from t where n < 5
4.每次从递归表 t中取出n,对n进行+1操作
select * from t;
5.查询递归表数据

image

上接内连接查询的案例,使用递归方式查询课程分类

with RECURSIVE t as (
select * from course_category as cc where  cc.id = '1'
union all
select c.* from course_category c INNER JOIN t on t.id = c.parentid
)
select * from t order by t.id,t.orderby;

t 表中的初始数据是id等于1的记录,即根结点。
image

通过 c inner join t on t.id = c.parentid 找到id='1'的下级节点 。
通过这种方法就找到了id='1'的所有下级节点,下级节点包括了所有层级的节点。
上边这种方法是向下递归,即找到初始节点的所有下级节点。

2.向上递归:从子节点开始向上找父节点

如何向上递归?
下边的sql实现了向上递归:

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

初始节点为1-1-1,通过递归找到它的父级节点,父级节点包括所有级别的节点。

mysql为了避免无限递归默认递归次数为1000,可以通过设置cte_max_recursion_depth参数增加递归深度,还可以通过max_execution_time限制执行时间,超过此时间也会终止递归操作。

标签:树型表,name,递归,id,查询,节点,select
From: https://www.cnblogs.com/lx0206/p/18244135

相关文章

  • MybatisPlus - [04] 分页查询
    limitm,n、PageHelper、MyBatisPlus分页插件 一、拦截器分页(1)在MybatisPlusConfig中进行配置@BeanpublicMybatisPlusInterceptorpaginationInterceptor(){MybatisPlusInterceptorinterceptor=newMybatisPlusInterceptor();interceptor.addInnerIntercep......
  • 在WEPAPI接口无法查询物料分组
     数据分组仅有业务对象没有实体表, 所以接口不能直接访问数据分组BOS_FORMGROUP通过表名反查业务对象标识,接口中使用查询到的业务对象标识可正常查询到数据.注意:可能存在分组没有对应的业务对象的情况,此时需要新建业务对象并设置对应的分组表. ......
  • presto 查询调度流程 (Coordinator Scheduler)
    basedontag:0.287presto的scheduler是SqlQueryScheduler这个类控制的,这个class主要是负责调度物理执行计划。调度具体的每个SqlStageExecution.这个Stage可以当成Fragment的一个概念他会先把所有的stage创建一个schedule计划。一共有两种schedule计划,一个是all-at-on......
  • ClickHouse内幕(3)基于索引的查询优化
    ClickHouse索引采用唯一聚簇索引的方式,即Part内数据按照orderbykeys有序,在整个查询计划中,如果算子能够有效利用输入数据的有序性,对算子的执行性能将有巨大的提升。本文讨论ClickHouse基于索引的查询算子优化方式。在整个查询计划中Sort、Distinct、聚合这3个算子相比其他算子......
  • Mybatis的查询功能
    MyBatis的各种查询功能如果查询出的数据只有一条,可以通过实体类对象接收List集合接收Map集合接收,如结果{password=123456,sex=男,id=1,age=23,username=admin}如果查询出的数据有多条,一定不能用实体类对象接收,会抛异常TooManyResultsException,可以通过实体类类型......
  • 情景题之小明的Linux实习之旅:linux实战练习1(上)【基础命令,权限修改,日志查询,进程管理...
    小明的Linux实习之旅:基础指令练习情景练习题背景介绍场景1:初识Linux,创建目录和文件场景2:权限管理,小明的权限困惑场景3:打包与解压,小明的备份操作场景4:使用Grep,小明的搜索技能场景5:系统服务管理,小明的首次接触场景6:进程管理,小明的多任务处理场景7:定时任务与系统状态场景8:d......
  • 如何判断 是否 需要 CSS 中的媒体查询
    以下是一些常见的使用媒体查询的场景:响应式布局:当设备的屏幕尺寸变化时,我们可以使用媒体查询来调整布局,以适应不同的屏幕尺寸。设备特性适配:我们可以使用媒体查询来检测设备的特性,如设备方向、分辨率、颜色能力等,并根据这些特性来应用不同的样式。优化打印样式:我们可......
  • 微信小程序源码-公交信息在线查询系统的计算机毕业设计(附源码+演示录像+LW)
    大家好!我是职场程序猿,感谢您阅读本文,欢迎一键三连哦。......
  • 微信小程序毕业设计-公交信息在线查询系统项目开发实战(附源码+演示视频+LW)
    大家好!我是岛上程序猿,感谢您阅读本文,欢迎一键三连哦。......
  • sql左连接查询时,右表的条件应该写在WHERE后面还是ON后面
    在SQL的左连接查询(LEFTJOIN)中,右表的条件应尽量写在ON子句后面。这是因为:ON子句:用于定义两个表之间的连接条件,决定了哪些行会从右表中选择出来与左表进行匹配。WHERE子句:用于过滤整个结果集,在连接操作完成之后应用。如果将针对右表的过滤条件放在WHERE子句而不是ON子句中,可能......