首页 > 数据库 >MySQL8.0新特性—CTE

MySQL8.0新特性—CTE

时间:2022-11-24 14:12:42浏览次数:40  
标签:name employees 特性 CTE MySQL8.0 333 id select

MySQL 8支持公用表表达式,包括非递归和递归两种。

公用表表达式允许使用命名的临时结果集,这是通过允许在SELECT语句和某些其他语句前面使用WITH子句来实现的。

不能在同一查询中两次引用派生表(子查询),因为那样的话,查询会根据派生表的引用次数计算两次或多次,这会引发严重的性能问题。使用CTE后,子查询只会计算一次。

非递归CTE

1. 派生表(子查询)

select …… from (subquery) as derived, table_name ……;

2. CTE

with derived as (
    subquery
)
select …… from derived, table_name ……;

CTE可能在SELECT/UPDATE/DELETE之前,包括with derived as (subquery)的子查询,例如:

with derived as (
    subquery
)
delete from table_name 
where table_name.col_name in (
    select col_name from derived
);

3. CTE可以引用其他CTE

with derived_one as (
    subquery
),
derived_two as (
    select …… from derived_one
)
select …… from derived_one, derived_two ……;

递归CTE

1. 语法解释

递归CTE是一种特殊的CTE,其子查询会引用自己的名字。WITH子句必须以WITH RECURSIVE开头。递归CTE子查询包括两部分:seed查询和recursive查询,由UNION[ALL]UNION DISTINCT分隔。

  • seed select被执行一次以创建初始数据子集;
  • recursive select被重复执行以返回数据的子集,直到获得完整的结果集。

当迭代不会生成任何新行时,递归会停止。这对挖掘层次结构(父/子或部分/子部分)非常有用。

with recursive {temp_table_name}(n) as (
    select …… from table_name  /* "seed select" */
    union all 
    select …… from {temp_table_name}, table_name  /* "recursive select" */
)
select …… from derived ……;

假设要打印从15的所有数字:

mysql> with recursive derived(n) as (
    -> select 1  /* "seed select" */
    -> union all 
    -> select n + 1 from derived where n < 5  /* "recursive select" */
    -> )
    -> select * from derived;
+------+
| n    |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
|    5 |
+------+
5 rows in set (0.00 sec)

在每次迭代中,SELECT都会生成一个带有新值的行,比前一行的值n1。第一次迭代在初始行集合(1)上运行并生成值为1 + 1 = 2的行;第二次迭代对第一次迭代的行集合(2)进行操作并生成值为2 + 1 = 3的行。以此类推,一直持续到n不再小于5时,递归结束。

2. 案例

假设要执行分层数据遍历,以便为每个员工生成一个组织结构图(即从CEO到每个员工的路径),也可以使用递归CTE

1. 创建带有manager_id的测试表

mysql> create table employees.employees_mgr ( 
    -> id int primary key not null,
    -> name varchar(100) not null,
    -> manager_id int null,
    -> index (manager_id),
    -> foreign key (manager_id) references employees_mgr (id)
    -> );
Query OK, 0 rows affected (0.03 sec)

2. 插入示例数据

mysql> insert into employees.employees_mgr values 
    -> (333, "Yasmina", null), /* Yasmina is the CEO (manager_id is null) */
    -> (198, "John", 333), /* John has id 198 and reports to 333 (Yasmina) */
    -> (692, "Tarek", 333),
    -> (29, "Pedro ", 198),
    -> (4610, "Sarah", 29),
    -> (72, "Pierre", 29),
    -> (123, "Adil", 692);
Query OK, 7 rows affected (0.01 sec)
Records: 7  Duplicates: 0  Warnings: 0

mysql> select id, name, manager_id from employees.employees_mgr;
+------+---------+------------+
| id   | name    | manager_id |
+------+---------+------------+
|   29 | Pedro   |        198 |
|   72 | Pierre  |         29 |
|  123 | Adil    |        692 |
|  198 | John    |        333 |
|  333 | Yasmina |       NULL |
|  692 | Tarek   |        333 |
| 4610 | Sarah   |         29 |
+------+---------+------------+
7 rows in set (0.00 sec)

3. 执行递归CTE

mysql> with recursive employee_paths (id, name, path) as (
    -> select id, name, cast(id as char(200))
    -> from employees.employees_mgr
    -> where manager_id is null
    -> union all
    -> select e.id, e.name, concat(ep.path, '->', e.id)
    -> from employee_paths as ep
    -> join employees.employees_mgr as e
    -> on ep.id = e.manager_id
    -> )
    -> select * from employee_paths;
+------+---------+--------------------+
| id   | name    | path               |
+------+---------+--------------------+
|  333 | Yasmina | 333                |
|  198 | John    | 333->198           |
|  692 | Tarek   | 333->692           |
|   29 | Pedro   | 333->198->29       |
|  123 | Adil    | 333->692->123      |
|   72 | Pierre  | 333->198->29->72   |
| 4610 | Sarah   | 333->198->29->4610 |
+------+---------+--------------------+
7 rows in set (0.00 sec)

with recursive employee_paths (id, name, path) asCTE的名称,列是(id, name, path)

select id, name, cast(id as char(200)) from employees.employees_mgr where manager_id is null是查询CEO的seed查询(没有在CEO之上的管理者)。

select e.id, e.name, concat(ep.path, '->', e.id) from employee_paths as ep join employees.employees_mgr as e on ep.id = e.manager_id是递归查询。

递归查询生成的每一行,会查找直接向前一行生成的员工做汇报的所有员工。对于每个员工,该行的信息包括员工ID、姓名和员工管理链,该链是在最后添加了员工ID的管理链。

标签:name,employees,特性,CTE,MySQL8.0,333,id,select
From: https://www.cnblogs.com/ciel717/p/16253268.html

相关文章

  • ida incompatible debugging server:debugger id is 1 expected 11
    image.png场景:调试夜神模拟器选择调试为androiddebugger,结果出现了这个错误​​incompatibledebuggingserver:debuggeridis1expected11​​因此改成lin......
  • 反射和特性
    反射一个运行的程序查看本身的元数据或者其他程序集的元数据的行为叫做反射。元数据,就是描述数据的数据。Metadata存在于任何对数据和数据关系的描述中,NET是基于面......
  • java.lang.IllegalArgumentException: Invalid character found in the request targe
    摘要:文件下载时,出现如下异常信息:2020-08-2416:18:35:136ErrorparsingHTTPrequestheaderNote:furtheroccurrencesofHTTPrequestparsingerrorswillbelogged......
  • postgresql 14新特性
    再说PostgreSQL14之前,先来带大家回复一下之前发布的各个版本和特性。PostgreSQL9.0:支持64位windows系统,异步流数据复制、HotStandby;PostgreSQL9.1:支持数据同步复制......
  • 记录一些JDK的新特性~持续更新
    1、record快速定义类@TestpublicvoidtestRecord(){/***JDK16新特性**@paramstart*@paramend......
  • Java帝国的诞生、Java的特性、Java的版本
    Java帝国的诞生C&C++1972年C诞生贴近硬件、运行极快、效率极高操作系统,编译器,数据库,网络系统等指针和内存管理1982年C++诞生面向对象兼容C图形领域、游戏等J......
  • java8新特性
    什么是函数式(Functional)接口只包含一个抽象方法的接口,称为函数式接口。你可以通过Lambda表达式来创建该接口的对象。(若Lambda表达式抛出一个受检异常(即:非运行时异常),那么......
  • 面向对象的三大特性
    ​ 面向对象的三大特性:封装:        我们把数据、一系列操作数据的函数封装到方法中,然后通过权限修饰符控制哪些方法可以让外知道,哪些只能自己知道,这样就能减少......
  • Karmada跨集群优雅故障迁移特性解析
    摘要:在Karmada最新版本v1.3中,跨集群故障迁移特性支持优雅故障迁移,确保迁移过程足够平滑。本文分享自华为云社区《​​Karmada跨集群优雅故障迁移特性解析​​》,作者:Karma......
  • 虚拟机软件VMware Fusion 13发布,增加了哪些新特性?
    macOS平台虚拟机软件VMwareFusion13Pro的正式版正式发布,新版本更新支持不少新特性,其中包括:支持macOSVentura13、支持虚拟TPM2.0模块与Windows11、支持在AppleSilico......