当前位置: 首页 > news >正文

【MySQL】MySQL 8.0 新特性之 - 公用表表达式(CTE)

MySQL 8.0 新特性之 - 公用表表达式(CTE)

  • 1. 公用表表达式(CTE) - WITH 介绍
    • 1.1 公用表表表达式
      • 1.1.1 什么是公用表表达式
      • 1.1.2 CTE 语法
      • 1.1.3 CTE示例
    • 1.3 递归 CTE
      • 1.3.1 递归 CTE 简介
      • 1.3.2 递归成员限制
      • 1.3.3 递归 CTE 示例
      • 1.3.4 使用递归 CTE 遍历分层数据
  • 2. CTE 与 Derived Table
    • 在 5.6 版本中
    • 在 5.7 版本中
    • 在 8.0 版本中

1. 公用表表达式(CTE) - WITH 介绍

1.1 公用表表表达式

1.1.1 什么是公用表表达式

官网:https://dev.mysql.com/doc/refman/8.0/en/with.html#common-table-expressions

MySQL 从 8.0 开始支持 WITH 语法,即:Common Table Expressions - CTE,共用表表达式。

CTE 是一个命名的临时结果集合,仅在单个 SQL 语句(select、insert、update 或 delete)的执行范围内存在。

派生表类似的是:CTE 不作为对象存储,仅在查询执行期间持续。与派生表不同的是:CTE 可以是自引用(递归CTE),也可以在同一查询中多次引用。此外,与派生表相比,CTE 提供了更好的可读性和性能。

1.1.2 CTE 语法

CTE 的结构包括:名称、可选列列表和定义 CTE 的查询。定义 CTE 后,可以像 select、insert、update、delete 或 create view 语句中的视图一样使用它。

with cte_name (column_list) as (query)
select * from cte_name;

查询中的列数必须与 column_list 中的列数相同。 如果省略 column_list,CTE 将使用定义 CTE 的查询的列列表。

1.1.3 CTE示例

初始化数据:

-- create table
create table department
(id        bigint auto_increment comment '主键ID'primary key,dept_name varchar(32)      not null comment '部门名称',parent_id bigint default 0 not null comment '父级id'
);-- insert values
insert into `department` values (null, '总部', 0);
insert into `department` values (null, '研发部', 1);
insert into `department` values (null, '测试部', 1);
insert into `department` values (null, '产品部', 1);
insert into `department` values (null, 'Java组', 2);
insert into `department` values (null, 'Python组', 2);
insert into `department` values (null, '前端组', 2);
insert into `department` values (null, '供应链测试组', 3);
insert into `department` values (null, '商城测试组', 3);
insert into `department` values (null, '供应链产品组', 4);
insert into `department` values (null, '商城产品组', 4);
insert into `department` values (null, 'Java1组', 5);
insert into `department` values (null, 'Java2组', 5);

(1)最基本的CTE语法:

mysql> with cte1 as (select * from `department` where id in (1, 2)),->      cte2 as (select * from `department` where id in (2, 3))-> select *-> from cte1->          join cte2-> where cte1.id = cte2.id;
+----+-----------+-----------+----+-----------+-----------+
| id | dept_name | parent_id | id | dept_name | parent_id |
+----+-----------+-----------+----+-----------+-----------+
|  2 | 研发部     |         1 |  2 | 研发部     |         1 |
+----+-----------+-----------+----+-----------+-----------+
1 row in set (0.00 sec)

(2)一个 CTE 引用另一个 CTE

mysql> with cte1 as (select * from `department` where id = 1),->      cte2 as (select * from cte1)-> select *-> from cte2;
+----+-----------+-----------+
| id | dept_name | parent_id |
+----+-----------+-----------+
|  1 | 总部       |         0 |
+----+-----------+-----------+
1 row in set (0.00 sec)

1.3 递归 CTE

1.3.1 递归 CTE 简介

递归CTE 是一个具有引用 CTE 名称本身的子查询的 CTE。递归 CTE 的语法为:

with recursive cte_name as (initial_query  -- anchor member
union all
recursive_query -- recursive member that references to the cte name
)
select * from cte_name;

递归 CTE 由三个主要部分组成:

  • 形成 CTE 结构的基本结果集的初始查询(initial_query),初始查询部分被称为锚成员。

  • 递归查询部分是引用 CTE 名称的查询,因此称为递归成员。递归成员由一个 union all 或 union distinct 运算符与锚成员相连。

  • 终止条件是当递归成员没有返回任何行时,确保递归停止。

递归 CTE 的执行顺序如下:

  1. 首先,将成员分为两个:锚点和递归成员。
  2. 接下来,执行锚成员形成基本结果集(R0),并使用该基本结果集进行下一次迭代。
  3. 然后,将 Ri 结果集作为输入执行递归成员,并将 Ri + 1 作为输出。
  4. 之后,重复第三步,直到递归成员返回一个空结果集,换句话说,满足终止条件。
  5. 最后,使用 union all 运算符将结果集从 R0Rn 组合。

1.3.2 递归成员限制

递归成功不能包含以下结构:

  • 聚合函数,如 max、min、sum、avg、count 等。
  • group by 子句
  • order by 子句
  • limit 子句
  • distinct

上述约束不适用于锚点成员。 另外,只有在使用 union 运算符时,要禁止 distinct 才适用。 如果使用 union distinct 运算符,则允许使用 distinct。

另外,递归成员只能在其子句中引用 CTE 名称,而不是引用任何子查询。

1.3.3 递归 CTE 示例

with recursive cte_count (n)as (select 1union allselect n + 1from cte_countwhere n < 3)
select n from cte_count;

在此示例中,以下查询:

select 1

是作为基本结果集返回 1 的锚成员。

以下查询:

select n + 1
from cte_count
where n < 3

是递归成员,因为它引用了 cte_count 的 CTE 名称。递归成员中的表达式 < 3 是终止条件。当 n 等于 3,递归成员将返回一个空集合,将停止递归。

下图显示了上述 CTE 的元素:

在这里插入图片描述
递归 CTE 返回以下输出:

+------+
|    n |
+------+
|    1 |
|    2 |
|    3 |
+------+

递归 CTE 的执行步骤如下:

  1. 首先,分离锚和递归成员。
  2. 接下来,锚定成员形成初始行 select 1,因此第一次迭代在 n = 1 时产生 1 + 1 = 2
  3. 然后,第二次迭代对第一次迭代的输出 2 进行操作,并且在 n = 2 时产生 2 + 1 = 3
  4. 之后,在第三次操作 n = 3 之前,满足终止条件 n <3 ,因此查询停止。
  5. 最后,使用 union all 运算符组合所有结果集1,2和3。

1.3.4 使用递归 CTE 遍历分层数据

查部门 id = 2 的所有下级部门和本级:

mysql> with recursive cte_tab as (select id, dept_name, parent_id, 1 as level->                            from department->                            where id = 2->                            union all->                            select d.id, d.dept_name, d.parent_id, level + 1->                            from cte_tab c->                                     inner join department d on c.id = d.parent_id-> )-> select *-> from cte_tab;
+------+-----------+-----------+-------+
| id   | dept_name | parent_id | level |
+------+-----------+-----------+-------+
|    2 | 研发部     |         1 |     1 |
|    5 | Java组    |         2 |     2 |
|    6 | Python组  |         2 |     2 |
|    7 | 前端组     |         2 |     2 |
|   12 | Java1组   |         5 |     3 |
|   13 | Java2组   |         5 |     3 |
+------+-----------+-----------+-------+
6 rows in set (0.00 sec)

2. CTE 与 Derived Table

针对 from 子句里面的 subquery,MySQL 在不同版本中,是做过一系列的优化,接下来我们就来看看。

在 5.6 版本中

MySQL 会对每一个 Derived Table 进行物化,生成一个临时表保存 Derived Table 的结果,然后利用临时表来完成父查询的操作,具体如下:

mysql> explain-> select * from (select * from department where id <= 1000) t1 join (select * from department where id >= 990) t2 on t1.id = t2.id;
+----+-------------+------------+------------+--------+---------------+---------+---------+----------------------------+------+----------+-------------+
| id | select_type | table      | partitions | type   | possible_keys | key     | key_len | ref                        | rows | filtered | Extra       |
+----+-------------+------------+------------+--------+---------------+---------+---------+----------------------------+------+----------+-------------+
|  1 | SIMPLE      | department | NULL       | range  | PRIMARY       | PRIMARY | 8       | NULL                       |    1 |   100.00 | Using where |
|  1 | SIMPLE      | department | NULL       | eq_ref | PRIMARY       | PRIMARY | 8       | pointer_mall.department.id |    1 |   100.00 | NULL        |
+----+-------------+------------+------------+--------+---------------+---------+---------+----------------------------+------+----------+-------------+
2 rows in set, 1 warning (0.01 sec)

在 5.7 版本中

MySQL 引入了 Derived Merge 新特性,允许符合条件的 Derived Table 中的子表与父查询的表进行合并,具体如下:

mysql> explain-> select * from (select * from department where id <= 1000) t1 join (select * from department where id >= 990) t2 on t1.id = t2.id;
+----+-------------+------------+------------+-------+---------------+-------------+---------+-------+---------+----------+-------------+
| id | select_type | table      | partitions | type  | possible_keys | key         | key_len | ref   | rows    | filtered | Extra       |
+----+-------------+------------+------------+-------+---------------+-------------+---------+-------+---------+----------+-------------+
|  1 | PRIMARY     | <derived2> | NULL       | ALL   | NULL          | NULL        | NULL    | NULL  |    1900 |   100.00 | NULL        |
|  1 | PRIMARY     | <derived3> | NULL       | ref   | <auto_key0>   | <auto_key0> | 8       | t1.id |    2563 |   100.00 | NULL        |
|  3 | DERIVED     | department | NULL       | range | PRIMARY       | PRIMARY     | 8       | NULL  | 4870486 |   100.00 | Using where |
|  2 | DERIVED     | department | NULL       | range | PRIMARY       | PRIMARY     | 8       | NULL  |    1900 |   100.00 | Using where |
+----+-------------+------------+------------+-------+---------------+-------------+---------+-------+---------+----------+-------------+
4 rows in set, 1 warning (0.00 sec)

在 8.0 版本中

我们可以使用 CTE 实现,其执行计划也是和 Derived Table 一样

mysql> explain-> with t1 as (select * from department where id <= 1000),->      t2 as (select * from department where id >= 990)-> select * from t1 join t2 on t1.id = t2.id;
+----+-------------+------------+------------+--------+---------------+---------+---------+----------------------------+------+----------+-------------+
| id | select_type | table      | partitions | type   | possible_keys | key     | key_len | ref                        | rows | filtered | Extra       |
+----+-------------+------------+------------+--------+---------------+---------+---------+----------------------------+------+----------+-------------+
|  1 | SIMPLE      | department | NULL       | range  | PRIMARY       | PRIMARY | 8       | NULL                       |    1 |   100.00 | Using where |
|  1 | SIMPLE      | department | NULL       | eq_ref | PRIMARY       | PRIMARY | 8       | pointer_mall.department.id |    1 |   100.00 | NULL        |
+----+-------------+------------+------------+--------+---------------+---------+---------+----------------------------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

从测试结果来看,CTE 似乎是 Derived Table 的一个替代品?其实不是的,虽然 CTE 内部优化流程与 Derived Table 类似,但是两者还是区别的,具体如下:

  1. 一个 CTE 可以引用另一个 CTE

  2. CTE 可以自引用

  3. CTE 在语句级别生成临时表,多次调用只需要执行一次,提高性能

从上面介绍可以知道,CTE 一方面可以非常方便进行 SQL 开发,另一方面也可以提升 SQL 执行效率。

相关文章:

【MySQL】MySQL 8.0 新特性之 - 公用表表达式(CTE)

MySQL 8.0 新特性之 - 公用表表达式&#xff08;CTE&#xff09;1. 公用表表达式&#xff08;CTE&#xff09; - WITH 介绍1.1 公用表表表达式1.1.1 什么是公用表表达式1.1.2 CTE 语法1.1.3 CTE示例1.3 递归 CTE1.3.1 递归 CTE 简介1.3.2 递归成员限制1.3.3 递归 CTE 示例1.3.4…...

基础面试题:C++中如何理解const修饰符

面试题目&#xff1a;1、题 int i10; const int*p &i; int *const* p &i; const在不同位置有什么不 同 2、const 修饰类成员变量是有什么特殊要求 3、const 修饰类成员函数会发什么 4、const 对象有什么意义 目录 前言 一、const的意义 二、const使用规则 1.初始化…...

在RT-Thread STM32F407平台下配置SPI flash为U盘

记录下SPI Flash U盘实现过程中踩过的坑&#xff0c;与您分享。前提条件是&#xff0c;需要先将SPI Flash 配置到elm fal文件系统&#xff0c;并挂载成功。如下图然后开始配置USB1&#xff0c;在CubeMX&#xff0c;选择SUB_OTG_FS2 选择USB Device3&#xff0c;确认USB时钟为48…...

数据存储技术复习(二)未完

module3存储是数据中心内的核心元素。请说明常用的存储选项及其特点。磁盘驱动器&#xff1a;具有很大的存储容量&#xff0c;随机读/写访问闪存驱动器&#xff1a;使用半导体介质&#xff0c;提供高性能&#xff0c;低功耗2&#xff0e;若某磁盘驱动器显示每个磁道有八个扇区&…...

使用 QuTrunk+Amazon Deep Learning AMI(TensorFlow2)构建量子神经网络

量子神经网络是基于量子力学原理的计算神经网络模型。1995年&#xff0c;Subhash Kak 和 Ron Chrisley 独立发表了关于量子神经计算的第一个想法&#xff0c;他们致力于量子思维理论&#xff0c;认为量子效应在认知功能中起作用。然而&#xff0c;量子神经网络的典型研究涉及将…...

python selenium浏览器复用技术

使用selenium 做web自动化的时候&#xff0c;经常会遇到这样一种需求&#xff0c;是否可以在已经打开的浏览器基础上继续运行自动化脚本&#xff1f; 这样前面的验证码登录可以手工点过去&#xff0c;后面页面使用脚本继续执行&#xff0c;这样可以解决很大的一个痛点。 命令行…...

第二章:创建虚拟机

创建Windows server&#xff1a;首先第一步就是打开我们的vm&#xff0c;然后找到上一章讲的主页图标创建新的虚拟机。点击这上面类似的&#xff0c;然后转站。博文地址&#xff1a;https://blog.csdn.net/ryduijftgvhj/article/details/127934939?spm1001.2014.3001.5502视频…...

码上【call,apply,bind】的手写

一、call &#xff08;1&#xff09;官方用法 call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。 语法&#xff1a;function.call(要绑定的this值&#xff0c;参数&#xff0c;参数&#xff0c;…)。不一定这些参数都需要&#xff0c;这些参数都…...

代谢组学Nature子刊!抑郁症居然“男女有别”,脑膜淋巴管起关键作用!

文章标题&#xff1a;A functional role of meningeal lymphatics in sex difference of stress susceptibility in mice 发表期刊&#xff1a;Nature Communications 影响因子&#xff1a;17.694 发表时间&#xff1a;2022年8月 作者单位&#xff1a;中山大学中山医学院 …...

nacos配置中心搭建

网站每次更新版本都有短暂暂停&#xff0c;影响用户使用&#xff0c;返回经常不可用&#xff0c;需要改进 需要实现高可用&#xff0c;搭建负载均衡&#xff0c;实现jenkinsnacos不停机部署 nacos搭建预备环境准备 64 bit OS&#xff0c;支持 Linux/Unix/Mac/Windows&#x…...

uni-app低成本封装一个取色器组件

在uni-ui中找不到对应的工具 后面想想也是 移动端取色干什么&#xff1f; 没办法 也挂不住特殊需求 因为去应用市场下载 这总东西 又不是很有必要 那么 下面这个组件或许能解决您的烦恼 <template><view class"content"><view class"dialog&…...

APP 怎么免费接入 MobPush

1、获取 AppKey 申请 Appkey 的流程&#xff0c;请点击 http://bbs.mob.com/thread-8212-1-1.html?fromuid70819 2、下载 SDK 下载解压后&#xff0c;如下图&#xff1a; 目录结构 &#xff08;1&#xff09;Sample&#xff1a;演示Demo。&#xff08;2&#xff09;SDK&am…...

XGBoost

目录 1.XGBoost推导示意图 2.分裂节点算法 Weighted Quantile Sketch 3.对缺失值得处理 1.XGBoost推导示意图 XGBoost有两个很不错得典型算法&#xff0c;分别是用来进行分裂节点选择和缺失值处理 2.分裂节点算法 Weighted Quantile Sketch 对于特征切点点得选择&#xff…...

你是什么时候从轻视到高看软件测试的?

刚开始学软件测试很轻视&#xff0c;因为我那时很无知&#xff0c;这也是那时绝大多数人员的心态&#xff0c;那时中国最讲究“编程才是硬道理”。 如今却非常热爱软件测试&#xff0c;包括软件测试工具&#xff0c;方法&#xff0c;理论&#xff0c;技术。因为我在3年的测试工…...

基于ssm的航空售票系统

博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经从做了六年的毕业设计程序开发&#xff0c;开发过上千套毕业设计程序&#xff0c;没有什么华丽的语言&#xf…...

滑动窗口最大值

给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。 示例: 输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3 输出: [3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 --------------- ----- [1 3 -1] -3 5 3 6 7 3 …...

接口文档参考示例

接口文档参考示例 用户登录 - POST /api/login/ 接口说明:登录成功后,会生成或更新用户令牌(token)。 使用帮助:测试数据库中预设了四个可供使用的账号,如下表所示。 Untitled 请求参数: Untitled 响应信息: 登录成功: {"code": 30000, "message&qu…...

2010-2019年290个城市经济发展与环境污染数据

2010-2019年290个城市经济发展与环境污染数据 1、时间&#xff1a;2010-2019年 2、统计口径&#xff1a;全市 3、来源&#xff1a;城市统计NJ&#xff0c;缺失情况与年鉴一致 4、指标包括&#xff1a; 综合经济&#xff1a;地区生产总值、人均地区生产总值、地区生产总值增…...

web开发

目录 使用Idea搭建Web项目 使用Idea开发Web项目基本知识 tomcat配置信息 HTML /CSS 开发主页 Servlet 学习和掌握的内容&#xff1a; HTML/CSSServlet MVC模式和Web开发数据库基本应用和JDBC应用软件项目开发流程 环境及工具版本&#xff1a; Windows10,JDK1.8 Idea2…...

【数据结构】优先级队列----堆

优先级队列----堆优先级队列堆堆的创建堆的插入&#xff1a;堆的删除&#xff1a;PriorityQueue的特性PriorityQueue的构造与方法优先级队列 优先级队列&#xff1a; 不同于先进先出的普通队列&#xff0c;在一些情况下&#xff0c;优先级高的元素要先出队列。而这种队列需要提…...

从零开始掌握30+种路径规划算法:可视化学习与实战指南

从零开始掌握30种路径规划算法&#xff1a;可视化学习与实战指南 【免费下载链接】PathPlanning Common used path planning algorithms with animations. 项目地址: https://gitcode.com/gh_mirrors/pa/PathPlanning 你是一个文章写手&#xff0c;你负责为开源项目写专…...

Spring Boot新手必看:从零搭建Web项目的5个关键步骤(附常见报错解决方案)

Spring Boot新手实战指南&#xff1a;从零构建Web应用的完整路线图 为什么选择Spring Boot作为你的第一个Java Web框架&#xff1f; 当你第一次接触Java Web开发时&#xff0c;面对众多框架的选择可能会感到迷茫。Spring Boot之所以成为大多数开发者的首选&#xff0c;是因为…...

3D打印键帽革命:如何用开源模型实现机械键盘的个性化定制

3D打印键帽革命&#xff1a;如何用开源模型实现机械键盘的个性化定制 【免费下载链接】cherry-mx-keycaps 3D models of Chery MX keycaps 项目地址: https://gitcode.com/gh_mirrors/ch/cherry-mx-keycaps 机械键盘爱好者们是否曾为寻找完美键帽而苦恼&#xff1f;传统…...

解决CLI工具接入DeepSeek API流式传输失败的实战指南

最近在对接DeepSeek的API时&#xff0c;遇到了一个挺典型的问题&#xff1a;用CLI工具调用API进行流式传输时&#xff0c;经常中途失败&#xff0c;返回的错误信息又比较模糊&#xff0c;调试起来很头疼。特别是在处理长文本生成或者需要连续对话的场景下&#xff0c;这个问题直…...

别再死记硬背了!用一次完整的网页访问,帮你彻底搞懂HCIA/HCIP里的TCP/IP和OSI模型

从输入网址到页面加载&#xff1a;用真实场景拆解TCP/IP与OSI模型 想象一下这个场景&#xff1a;你在浏览器地址栏输入"www.baidu.com"&#xff0c;按下回车键&#xff0c;不到一秒就看到了熟悉的搜索页面。这看似简单的操作背后&#xff0c;隐藏着一场精密的网络协议…...

Llama-3.2V-11B-cot部署教程:双卡4090一键启动视觉推理工具

Llama-3.2V-11B-cot部署教程&#xff1a;双卡4090一键启动视觉推理工具 1. 项目概述 Llama-3.2V-11B-cot是基于Meta多模态大模型开发的高性能视觉推理工具&#xff0c;专为双卡4090环境优化。它解决了传统大模型部署复杂、视觉权重加载失败等痛点&#xff0c;让普通用户也能轻…...

哈尔滨全屋定制厂家:值得信赖的筛选逻辑深度解析

哈尔滨全屋定制厂家筛选逻辑深度解析&#xff1a;5步找到值得信赖的本地品牌 “哈尔滨全屋定制厂家选择&#xff0c;不是看广告多响&#xff0c;而是这5个筛选逻辑能帮你避开90%的坑”。对于准备在哈尔滨做全屋定制的业主来说&#xff0c;选对厂家直接决定了最终效果与性价比&…...

深度解析开源工具如何实现游戏性能优化:Genshin FPS Unlocker专业实战指南

深度解析开源工具如何实现游戏性能优化&#xff1a;Genshin FPS Unlocker专业实战指南 【免费下载链接】genshin-fps-unlock unlocks the 60 fps cap 项目地址: https://gitcode.com/gh_mirrors/ge/genshin-fps-unlock Genshin FPS Unlocker 是一款专注于游戏性能优化的…...

勒索病毒突发中招?紧急处置+自救恢复全指南(2026实战版),收藏这篇就够了!

勒索病毒突发中招&#xff1f;紧急处置自救恢复全指南&#xff08;2026实战版&#xff09; “文件全被加密&#xff0c;桌面弹出勒索信&#xff0c;要求48小时内支付比特币赎金”——勒索病毒的突发性让无数个人用户和企业猝不及防。一旦中招&#xff0c;核心文件被锁、业务中…...

央国企稳岗扩岗新举措解读

近日&#xff0c;国家层面再次强调了就业优先战略的重要性&#xff0c;并推动相关政策措施进一步升级。在这一宏观背景下&#xff0c;中央企业和国有企业作为国民经济的重要支柱&#xff0c;其在稳就业、扩岗位方面的举措备受关注。一系列新的行动方案正陆续出台&#xff0c;旨…...