MySQL with recursive 用法浅析

目录

写在前面

语句功能

with recursive 语法讲解

细节补充

“union all”语句

添加递归终止条件


写在前面

介绍“with recursive”用法的文章不少,但我都觉得讲的不够通俗,所以干脆自己写一篇。话不多说,进入正题。

语句功能

with recursive用于在MySQL中进行递归查询,另外由于树形结构的数据存储,在进行查询时,就是通过递归来实现的,所以很多人接触with recursive就是由于要对树形结构的数据进行查询。但你还是要区分清楚,with recursive并不局限于树形结构的查询,而是只要你需要递归查询,就可以用他。

with recursive 语法讲解

首先吐槽一下,MySQL的with recursive之所以让人在第一次接触的时候感觉不好理解,我个人觉得主要是他这个语法的设计问题,说白了就是这个语法看起来就让人感觉很迷惑,你要是接触过oracle那个递归查询的语法,会发现语法非常精简,很“见名知意”,属于那种几乎不用学习,你看别人写的一个例子,就可以模仿实现自己的需求的。接下来开始讲解,我们先来看个例子。

假设现在有一个公司里的部门信息表,名字叫“department”,除了存放部门信息外,也存储了表的层级关系,大概是这样的:

部门信息表
idnameparent_idlevel
1总经理1
2总经理办公室12
3研发部12
4人事部23
5采购部23
6java开发部33
7前端开发部33

“parent_id”表示当前节点的父节点的id,“level”表示当前节点所在的层级,如果对上面这张表进行递归查询,语法是这样的:

with recursive t1 as (select * from department where id = '3'union allselect * from department t2 inner join t1 on t1.id = t2.parent_id
)select * from t1;

这个语句表示从研发部开始,查询研发部的所有子节点,直到树的底部。如果想查询整张表,那就需要从根节点开始,把条件改为“id = '1'”,由于总经理是根节点,就相当于查询整张表。

接下来讲解这个语法,首先“with recursive”的语法有一部分是基本固定的:

with recursive t1 as (union all)select * from t1;

上面这个结构是基本固定的,这个临时表名“t1”你可以改成什么a1、b1、c2都可以,只要用到临时表名的地方一起改就行。剩下的主要就是“union all”上下的两句sql怎么写,在这之前,我们先来看一下,抛开sql语句,单纯的在一棵树里面进行一次递归查询的逻辑是怎样的:

先选中一个节点,查询该节点的所有子节点(假设有n个子节点),然后,再查询这n个子节点的所有子节点(假设有m个子节点),一直循环(也就是递归),到什么时候结束呢,到树的底部,或者你也可以指定查询到某一层。

当然这种从上往下查的看起来相对复杂一点,递归也可以从下往上查,这样简单一些,那么逻辑就是:

先选中一个节点,查询该节点的父节点,然后,继续查询这个父节点的父节点,一直循环(也就是递归),直到树的根节点,或者也可以指定查询到某一层。

 不论从上往下查,还是从下往上查,这里面的关键信息有三个:

  1. 选中一个节点,也就是递归的起点;
  2. 查询这个节点的下一个节点(如果是从上往下查,就是子节点,如果是从下往上查,就是父节点),但是数据库怎么知道下一个节点是谁呢,这个你才知道,你要告诉数据库,两个节点之间的关联条件;
  3. 查到哪里结束,也就是递归的终点。

现在我们再重新看“with recursive”的语法:

with recursive t1 as (//语句1select * from department where id = '3'union all//语句2select * from department t2 inner join t1 on t1.id = t2.parent_id
)select * from t1;

说明:

语句1:是在说明递归的起点,这里就指定从研发部开始递归。

语句2:是在说明当前节点和下一个节点的关联条件,注意看他是怎么表达两个节点的关联条件的,是以连接查询的语法来表达两个节点的关联条件,使用最外层的“with recursive t1”定义的临时表名“t1”来表示当前节点所在的表,另外一个“department”则表示下一个节点所在的表。这条语句本身是从上往下查,所以最后的关联条件就是当前表的id值等于下一张表的parent_id值。

递归的终点在哪呢?上面的例子没有指定递归的重点,所以实际会一直查询到树的底部,如果想指定递归的终点,则是在语句2中指定,像下面这样就是通过表里的某个字段来指定递归的终点:

select * from department t2 inner join t1 on t1.id = t2.parent_id where t2.level < 4;

到此,with recursive 的基本用法就讲解完毕了,注意一下,整个“with as recursive t1 ()”语句都只是在定义递归的逻辑,最下面那行“select * from t1”才是真正的在执行查询,你别把最后这行给漏掉了

接下来我们验证一下你是否真的学会了。如果你真的理解了“with recursive”的语法,那么上述例子当中的那张表,如果把需求改成从下往上查,你应当能看懂下面的查询语句:

with recursive t1 as (//语句1select * from department where id = '3'union all//语句2select * from department t2 inner join t1 on t1.parent = t2.id
)select * from t1;

语句1:并没有做修改,因为不需要改变递归的起点,只是需求由查询研发部的所有子节点,改成了查询研发部的所有父节点。

语句2:唯一的改动点就在这里,最后面的关联条件给改了,既然是从下往上查,那么应当是当前表的parent_id字段和下一张表的id字段关联。

细节补充

“union all”语句

注意一下递归查询里面的union all语句是遵循union all的语法的,也就是他上下两个语句里面的列是要一致的,以上述那张表为例,如果你不使用“*”,而是指定列的话,两条语句指定的列是需要一致的:

with recursive t1 as (//语句1select id, name, parent_id from department where id = '3'union all//语句2select t2.id, t2.name, t2.parent_id from department t2 inner join t1 on t1.id = t2.parent_id
)select * from t1;

添加递归终止条件

最后在补充一个带了递归终止条件的SQL语句示例:

with recursive t1 as (//语句1select id, name, parent_id from department where id = '3'union all//语句2select t2.id, t2.name, t2.parent_id from department t2 inner join t1 on t1.id = t2.parent_idwhere t2.level < 4
)select * from t1;

结束,goodbye。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/50382.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构】二叉树链式结构——感受递归的暴力美学

前言&#xff1a; 在上篇文章【数据结构】二叉树——顺序结构——堆及其实现中&#xff0c;实现了二叉树的顺序结构&#xff0c;使用堆来实现了二叉树这样一个数据结构&#xff1b;现在就来实现而二叉树的链式结构。 一、链式结构 链式结构&#xff0c;使用链表来表示一颗二叉树…

python kivy制作GUI界面---ScreenManager多界面跳转

目录 介绍项目演示代码示例介绍 由于开了新的项目,需要制作适合一次开发多端多环境运行的桌面端项目,找了大部分的项目,目前主推的框架主要有:kivy、wxpython、electron等可以快速开发的,由于项目预测体积不会太大,所以暂时不考虑PyQt啦,多了不少,少了不唠,直接进入主…

FPGA:有限状态机

从以下6个实验理解状态机的概念 开发板频率为 50 M H z 50MHz 50MHz&#xff0c;一个时钟周期是 20 n s 20ns 20ns。 1、实验一:LED灯亮0.25秒、灭0.75秒的状态循环 通过之前的分析&#xff0c;我们实现频闪灯时&#xff0c;是让led灯在0.5秒实现一次翻转&#xff0c;而这里…

【我的OpenGL学习进阶之旅】讲一讲GL_TEXTURE_2D和GL_TEXTURE_EXTERNAL_OES的区别

在使用OpenGL ES进行图形图像开发时,我们常使用GL_TEXTURE_2D纹理类型,它提供了对标准2D图像的处理能力。这种纹理类型适用于大多数场景,可以用于展示静态贴图、渲染2D图形和进行图像处理等操作。 另外,有时我们需要从Camera或外部视频源读取数据帧并进行处理。这时,我们…

经典文献阅读之--World Models for Autonomous Driving(自动驾驶的世界模型:综述)

Tip: 如果你在进行深度学习、自动驾驶、模型推理、微调或AI绘画出图等任务&#xff0c;并且需要GPU资源&#xff0c;可以考虑使用UCloud云计算旗下的Compshare的GPU算力云平台。他们提供高性价比的4090 GPU&#xff0c;按时收费每卡2.6元&#xff0c;月卡只需要1.7元每小时&…

linux-conda环境安装配置教程

以下是一个超详细的Linux-Conda环境安装教程,该教程涵盖了从系统准备到环境配置的全过程: 一、准备工作 确认系统环境: 确认操作系统的版本和系统架构。可以通过以下命令获取这些信息:uname -a lsb_release -a这些命令将显示你的内核版本、系统名称、硬件架构和操作系统版…

html+css 实现水波纹按钮

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享htmlcss 绚丽效果&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 文…

python重命名图片

在Python中&#xff0c;获取图片路径并根据当前时间戳重命名图片通常涉及以下几个步骤&#xff1a; 确定图片的原始路径&#xff1a;首先&#xff0c;你需要知道图片的当前位置。获取当前时间戳&#xff1a;然后&#xff0c;使用Python的datetime模块来获取当前时间的时间戳。…

vue3前端开发-小兔鲜项目-使用pinia插件完成token的本地存储

vue3前端开发-小兔鲜项目-使用pinia插件完成token的本地存储&#xff01;实际业务开发中&#xff0c;token是一个表示着用户登录状态的重要信息&#xff0c;它有自己的生命周期。因此&#xff0c;这个参数值必须实例化存储在本地中。不能跟着pinia。因为pinia是基于内存设计的模…

事务和函数索引

事务 事务的定义 事务&#xff08;Transaction&#xff09;&#xff0c;就是将一组SQL语句放在同一批次内去执行&#xff0c;如果一个SQL语句出错&#xff0c;则该批次内 的所有SQL都将被取消执行。 事务的特点 一个事务中如果有一个数据库操作失败&#xff0c;那么整个 事务…

若依框架 : 生成代码

6.生成代码 6.1.配置生成设置 ruoyi-generator -> src -> main -> resources -> generator.yml 由于 案例中 表都有 前缀 为 tta_ , 这里设置去掉 6.2.生成代码 6.2.1.导入数据库中的表 6.2.2.修改设置 6.2.2.1.设置生成信息 点击 编辑 -> 生成信息 特别…

SqlServer 使用T-SQL单纯的复制表数据

今天用Sql Server Manager Studio 先复制一个库建立一个新库出来&#xff0c;各种报错&#xff0c;也不知道是为什么&#xff0c;连备份再还原都不行&#xff0c;算了&#xff0c;自己写个SQL 脚本来执行算了...... 坏处是视图&#xff0c;存储过程和函数都没有复制过来 -- 设…

m4a怎么转mp3?m4a转mp3的几种方法教程

m4a怎么转mp3&#xff1f;M4A音频格式的全称MPEG-4 Audio&#xff0c;是一种音频压缩格式。这种格式以其卓越的音质和相对较小的文件大小而广受欢迎&#xff0c;尤其是在音乐存储、在线流媒体以及音频编辑等领域。M4A格式被广泛应用于苹果公司的产品中&#xff0c;如iPhone、iP…

开放式耳机会成为未来的主流吗?开放式耳机推荐指南

开放式耳机是否会成为未来的主流&#xff0c;是一个值得探讨的问题。 从目前的市场趋势和技术发展来看&#xff0c;有一些因素支持开放式耳机可能成为主流。 一方面&#xff0c;人们对于健康和舒适的关注度不断提高。长时间佩戴传统耳机可能导致耳部不适&#xff0c;而开放式…

在Linux中,部署及优化Tomcat

tomcat概述 自 2017 年 11月编程语言排行榜 Java 占比 13%,高居榜首&#xff0c;Tomcat 也一度成为 Java开发人员的首选。其开源、占用系统资源少、跨平台等特性深受广大程序员喜爱。本章主要学习如何部署 Tomcat 服务&#xff0c;根据生产环境实现多个虚拟主机的配置&#xf…

【QGroundControl二次开发】五.python生成自定义MAVLink消息及使用

一 . 环境配置 参考&#xff1a; MAVLink代码生成-C# 二. 生成MAVLINK协议 在MAVlink源码下找到message_definitions/common.xml&#xff0c;修改其中的内容。 例如&#xff1a; <message id"12" name"DISTANCE_SENSOR"><description>Dedi…

【Code Complete2】Note-1 [启发式编程、管理复杂度、隐藏设计]

【Code Complete2】_Note-1 [启发式编程、管理复杂度、隐藏设计] 文章目录 【Code Complete2】_Note-1 [启发式编程、管理复杂度、隐藏设计]启发式编程管理复杂度隐藏设计--减少“改动所影响的代码量” 启发式编程 ​ **设计是一个启发的过程&#xff0c;充满了不确定性&#…

记录|cmd方式恢复U盘中的数据

目录 前言一、CMD恢复Step1.Step2. 更新时间 前言 参考文章&#xff1a; u盘数据误删怎么恢复&#xff1f;安利8款数据恢复软件免费版&#xff08;2024 NEW&#xff09; 回家后&#xff0c;家人说U盘里的歌突然没有了。我就用电脑看了看&#xff0c;发现电脑中能看到U盘中是满的…

nodejs和vue做web版的MySQL数据库设计

要使用 Node.js 和 Vue.js 创建一个 Web 版本的 MySQL 数据库设计工具,需要构建一个前后端分离的应用程序。下面开始从易到难构建应用程序。 1. 环境准备 确保你的开发环境中安装了以下软件: Node.jsnpm (Node.js 包管理器)MySQL 数据库Vue.js CLI (可选)2. 创建项目结构 …

修改启动方案

AMP设置为1Linux&#xff08;CPU0&#xff09; 3HAL&#xff08;CPU1、 2、 3&#xff09; 配置。 用vscode打开its 配置文件rk3568_amp_linux.its文件修改 /* SPDX-License-Identifier: BSD-3-Clause */ /** Copyright (c) 2022 Rockchip Electronics Co., Ltd.*//dts-v1/; /…