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

MySQL:CTE 通用表达式

CTE(Common Table Expression,通用表达式)在 SQL 查询中定义临时结果集的一种方法,它可以让查询更加简洁、可读性更高,并且可以重复引用。

CTE 是在WITH关键字后面定义的一个子查询,可以在同一查询中被引用多次。它可以被认为是一个临时表,只在定义它的查询(例如:SELECTINSERTDELECTUPDATE)中可见,并且这个临时表的生命周期仅限于当前查询,不作为对象被存储

不同于派生表(Derived Table)CTE可以是自引用的(递归CTE),也可以在
同一查询中多次引用。此外,与派生表相比,CTE提供了更好的可读性和性能。

语法格式如下:

WITH cte_name [column_list] AS(-- CTE querySELECT column1,column2,...FROM table_nameWHERE condition...;
)
SELECT columnlist FROM cte_name;
  • CTE query 中的字段数必须与column_list的字段数相同,若省略column_list,CTE将会使用 CTE query 中的columns

  • 还可以使用两个或以上CTE作为临时表进行查询

  • CTE 查询定义部分使用 SELECT 语句定义了结果集的内容,可以包含各种查询操作和条件。它的结果集将成为 CTE 的数据。

  • 在主查询部分,可以引用 CTE 的名称来访问 CTE 查询部分定义的结果集。

CTE 优点

  • 简化查询逻辑:CTE 允许在查询中使用递归、复杂的子查询或多个操作步骤,以更清晰、易读的方式组织查询逻辑。

  • 重用和可读性:在同一个查询中多次引用 CTE,避免了重复的子查询,提高了查询的可读性和重用性。

  • 性能优化:某些情况下,使用 CTE 可以帮助数据库管理系统进行优化,减少重复查询的开销。

WITH 关键字

WITH 是在 SQL 查询中使用的关键字,用于定义一个或多个通用表达式(Common Table Expression,CTE)。

WITH … INSERT…

在传统的 INSERT 语句中,需要分别指定目标表和要插入的值,而使用 WITH INSERT 技术,可以 先使用 WITH 子句定义一组数据,然后在 INSERT 语句中引用这个临时的数据集合进行插入。基本模式如下:

WITH cte_name [column_list] AS(initial_query[UNION ALLrecursive_query]...
)
INSERT INTO table_name (column_list)
SELECT column_list FROM cte_name
WHERE condition;

CTE 查询定义部分使用 SELECT 语句定义要插入的数据集合,可以使用 UNION ALL 连接多个 SELECT 语句来构建数据。

最后,在 INSERT INTO 语句中,可以引用定义好的 CTE 数据集合,并将其插入到目标表中。

WITH INSERT 技术并非所有数据库管理系统都支持,具体支持与否要参考所使用数据库的文档。

WITH… UPDATE…

传统的 UPDATE 语句需要指定目标表、要更新的列以及更新的值,使用 WITH UPDATE 技术,可以 先使用 WITH 子句定义一个临时的查询结果集,然后在 UPDATE 语句中引用该结果集进行更新:

WITH cte_name AS(query
)
UPDATE table_name
SET column1 = cte_name.column1,column2 = cte_name.column2,...
FROM cte_name
WHERE table_name.primary_key = cte_name.primary_key;

UPDATE 语句中,可以使用 FROM 子句引用定义好的 CTE,将其与目标表进行联结,并使用 CTE 中的列来更新目标表中对应的列。

WITH UPDATE 技术并非所有数据库管理系统都支持,具体支持与否要参考所使用数据库的文档

WITH… DELETE…

传统的 DELETE 语句需要指定目标表以及删除条件,使用 WITH DELETE 技术,可以 先使用 WITH 子句定义一个临时的查询结果集,然后在 DELETE 语句中引用该结果集进行删除

WITH cte_name AS(query
)
DELETE FROM table_name
WHERE table_name.primary_key IN (SELECT primary_key FROM cte_name);

DELETE 语句中,可以使用 WHERE 子句配合子查询使用定义好的 CTE,以指定要删除的数据的条件。

WITH DELETE 技术并非所有数据库管理系统都支持,具体支持与否要参考所使用数据库的文档

WITH in Subqueries

WITH 子句还可以在子查询或派生表子查询中使用:

SELECT column_list FROM table1
WHERE column1 IN (WITH cte_name AS (query));SELECT * 
FROM (WITH cte_name AS (query)) AS derived_table;

其他应用

WITH 子句还可以用在所有包含 SELECT 子句的语句中,位于SELECT之前

CREATE TABLE ... WITH ... SELECT ...
CREATE VIEW ... WITH ... SELECT ...
INSERT ... WITH ... SELECT ...
REPLACE ... WITH ... SELECT ...
DECLARE CURSOR ... WITH ... SELECT ...
EXPLAIN ... WITH ... SELECT ...

Recursive CTE

CTE 支持递归,recursive CTE 是具有引用 CTE自身 的 子查询 的 CTE,使用RECURSIVE 关键字进行声明:

WITH RECURSIVE cte_name AS(initial_query  -- anchor memberUNION [ALL | DISTINCT]recursive_query  -- recursive member that --                  references to the CTE name
)
SELECT * FROM cte_name;
递归 CTE 的组成部分

递归CTE包含三个部分:

  1. initial query:形成CTE结构的基本结果集。初始查询部分被称为锚成员(anchor member)。

  2. recursive query:引用CTE名称的查询,通过UNION ALL或UNION DISTINCT操作符与锚成员连接。

  3. termination condition:确保在递归成员不返回任何行时停止递归

'''示例'''
WITH RECURSIVE cte_count (n) 
AS (-- anchor memberSELECT 1  UNION ALL-- recursive memberSELECT n + 1 FROM cte_count -- termination conditionWHERE n < 3)
SELECT n 
FROM cte_count;
递归 CTE 的执行顺序
  1. 将成员分成两个:anchor memberrecursive member

  2. 执行锚成员以形成基本结果集(R0),并将此基本结果集用于下一次迭代。

  3. Ri 结果集作为输入执行递归成员,并将 Ri+1 作为输出。

  4. 重复第三步,直到递归成员返回空结果集(满足终止条件)。

  5. 使用 UNION ALL 运算符组合从 R0Rn 的结果集。

递归成员限制

recursive member 禁止包含

  • 聚合函数:MAX(),MIN(),SUM(),AVG(),COUNT() 等

  • GROUP BY 子句

  • ORDER BY 子句

  • LIMIT 子句

  • DISTINCT 子句

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 洛克兄弟:E-Bike浪潮下的骑行配件10亿大卖独立站拆解丨出海笔记
  • Android 更换applicationId 后 微信没有回调
  • 【自动化测试工具详解】使用Selenium、JUnit等工具进行自动化测试
  • 漏洞挖掘 | edusrc记一次某中学小程序渗透测试
  • 深入解析汽车VCU:新能源汽车的“大脑”
  • TCP/IP_TCP协议
  • 每天一个数据分析题(四百六十一)- AR模型
  • 关于Unity四种合批技术详解
  • 引领未来交通新纪元:综合智慧监管平台
  • linux安装人大金仓数据库
  • 【全网最全】文心智能体平台介绍和应用
  • 【第六节】python的特殊语法和常用模块
  • html写table表格,后端数据中涉及到身份证号或者电话号的情况,生成excel变成1+e17或者###等类似的加密或科学计数法情况
  • Encoder-Decoder:Seq2seq
  • Day12--Servlet实现前后端交互(案例:学生信息管理系统登录页面)
  • 深入了解以太坊
  • angular2开源库收集
  • JS正则表达式精简教程(JavaScript RegExp 对象)
  • Magento 1.x 中文订单打印乱码
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • Vue组件定义
  • 初探 Vue 生命周期和钩子函数
  • 第十八天-企业应用架构模式-基本模式
  • 关于extract.autodesk.io的一些说明
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 文本多行溢出显示...之最后一行不到行尾的解决
  • 项目管理碎碎念系列之一:干系人管理
  • 小程序 setData 学问多
  • (13)Latex:基于ΤΕΧ的自动排版系统——写论文必备
  • (BFS)hdoj2377-Bus Pass
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (react踩过的坑)antd 如何同时获取一个select 的value和 label值
  • (不用互三)AI绘画工具应该如何选择
  • (附源码)spring boot球鞋文化交流论坛 毕业设计 141436
  • (深入.Net平台的软件系统分层开发).第一章.上机练习.20170424
  • (转)Windows2003安全设置/维护
  • (转)程序员技术练级攻略
  • .bat批处理(六):替换字符串中匹配的子串
  • .gitignore文件—git忽略文件
  • .NET 3.0 Framework已经被添加到WindowUpdate
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地中转一个自定义的弱事件(可让任意 CLR 事件成为弱事件)
  • .net2005怎么读string形的xml,不是xml文件。
  • .net开发引用程序集提示没有强名称的解决办法
  • .NET面试题解析(11)-SQL语言基础及数据库基本原理
  • .NET设计模式(11):组合模式(Composite Pattern)
  • [240903] Qwen2-VL: 更清晰地看世界 | Elasticsearch 再次拥抱开源!
  • [Angular] 笔记 9:list/detail 页面以及@Output
  • [C++]拼图游戏
  • [C++]入门基础(1)
  • [C语言]-基础知识点梳理-文件管理
  • [EFI]Lenovo ThinkPad X280电脑 Hackintosh 黑苹果引导文件
  • [flutter]一键将YAPI生成的api.json文件转为需要的Dart Model类的脚本
  • [Geek Challenge 2023] web题解
  • [HeMIM]Cl,[AeMIM]Br,[CeEIM]Cl,([HO-PECH-MIM]Cl,[HOOC-PECH-MIM]Cl改性酚醛树脂
  • [Hive]五、Hive 源码编译