【新星计划】数据库 CTE 初识

news2024/11/29 20:44:50

【新星计划】数据库 CTE 初识

  • CTE
    • CTE 语法
  • CTE 递归
    • CTE 递归语法
    • 递归示例
    • 递归机制
  • 几个CTE 递归的示例
    • 阶乘
    • 斐波那契序列
    • 无限级分类路径
  • rand 函数
  • 小结

CTE

CTE指的是公共表表达式(Common Table Expression)

在日常我们使用数据库的时候,通常在一些数据汇总计算的时候,会用到临时表,或者变量或者其他辅助手段,来保存一些数据,然后与现有数据进行计算。

一个非常典型的例子,比如有一次考试,统计各个分数段的考生各有多少人,占考生比例为多少,平均分是多少,大于平均分的有多少人,占比多少。

在这个需求中,我们可以用以下几种方法

1、使用变量存储两个数据,平均值和总数
2、使用临时表存储这两个数据
3、使用子查询得出这两个数据

然后和汇总数据进行比较得出最后结果,但是,如果需求再复杂一点的时候,比如各个班的平均分是多少,总平均分是多少,那么使用变量方式就无法做到了。

而使用子查询方式,有一个很大的痛点,那就是,每个子查询只能使用一次,无法复用。

最后,临时表方式能解决这些问题,但是,也有不方便的地方,我们需要将查询分成多个部分,最后还要记得注销临时表

由于以上三种方式都有各自的痛点,所以在 SqlServer 2005 的时候,追加了另外一种方式,也就是 CTE 查询方式。而在 MySql ,则在 MySql v8 以上版本也得到了支持。

使用 CTE 有一些基本的优点:

1、查询结果可复用
2、可对查询结果生成多个 CTE 结果,互不干扰
3、数据存放在内存中,每次使用完毕后自动注销

CSDN 文盲老顾的博客, https://blog.csdn.net/supewrfei

CTE 语法

# MySql & MsSql
with cte as (
    select data1 colName1,data2 colName2
)
select * from cte;

with cte (colName1,colName2) as (
	select 1,2
)
select * from cte

基本 CTE 语法,在 MySql 和 MsSql 都一样,唯一需要注意的是,当出现多个查询时,MySql 因为每个指令都要求有分号,所以不会出现异常情况。而 MsSql 因为可以多个指令之间不用分号间隔,所以在多个指令中使用 cte 时,要在 with 前加一个分号,强制结束之前的指令,避免出现将 with 当做前一个指令查询后续部分。

老顾用 CTE 基本查询,更多的是用来模拟数据,减少了临时表的操作。

CTE 递归

在数据库中,使用了CTE后,发现优势比临时表多不到哪里去,一点也体现不出存放在内存中的优势,所以 CTE 做了一个骚操作:递归。

CTE 递归语法

# MySql 
with RECURSIVE CTE as (
    select data1 
    from sourceTable
    union all
    select * 
    from sourceTable,CTE
)
select * from CTE

# MsSql
    select data1 
    from sourceTable
    union all
    select * 
    from sourceTable,CTE
)
select * from CTE

在这里稍微有一点点不同,MySql 如果要使用CTE递归,必须对这个 CTE 做一个RECURSIVE 关键词修饰,而 MsSql 则无需多余的修饰。

递归示例

对于递归,我们先用一个最简单的例子来展示一下,生成100行数据,每行数据一个列,存放一个数字表示当前行顺序

with RECURSIVE t as (
	select 1 id
	union all
	select id + 1 
	from t
	where id < 100
)
select * from t;

指令通用的,MsSql 去掉 recursive 关键字修饰即可使用。通过这个例子,我们可以很方便的得到一个连续的数字区间。这对于数据补全丢失部分,有很大的帮助。

在 MsSql 中,递归默认不允许超出递归100次,如果一定要超出这个限制,需要通过 option 来指定递归限制数量,需要注意的是,该参数是在使用递归数据的查询位置,而不是在递归内

with t as (
	select 1 id
	union all
	select id+ 1 from t where id<200
) 
select * from t option(MAXRECURSION 0)

递归机制

那么,如果我们想知道,到底递归是怎么进行的,比如一次递归可以产生多少数据,每次递归都传递了哪些内容。

那么老顾做一个查询,来测试一下。

with RECURSIVE t as (
	select 1 id
	union all
	select id + 1 
	from t
	where id < 100
),t1 as (
	select *,1 tm 
	from t 
	where id < 5
	union all
	select t.*,tm + 1 
	from t,t1 
	where t.id=t1.id+1
)
select * from t1
order by tm,id;

在这里插入图片描述
我们对于 t1 这个 cte 递归表的第一部分,选择了四条数据,然后递归的时候,每次都会得到另外四条数据,我们通过 tm 就可以看到递归的层级。
在这里插入图片描述
然后,我们借助一下排名函数,来确定一下递归的更进一步的机制。

3575 - Recursive Common Table Expression ‘t1’ can contain neither aggregation nor window functions in recursive query block

但由于 MySql 不能在递归内使用排名函数,所以这次用MsSql 的指令看看结果。

with t as (
	select 1 id
	union all
	select id + 1 
	from t
	where id < 100
),t1 as (
	select *,1 tm,row_number() over(order by id) grp 
	from t 
	where id < 5
	union all
	select t.*,tm + 1,row_number() over(order by t.id) grp  
	from t,t1 
	where t.id=t1.id+1
)
select * from t1;

在这里插入图片描述
在这里插入图片描述

可以看到,除了递归入口的四条数据,其他数据的排名结果都是1,所以递归机制基本可以确定了。

1、递归方式为每次选出一条数据,作为递归数据传递
2、递归可以由一条数据产生多条数据,但不得产生与递归数据相同的数据,避免进入死循环
3、递归应该有跳出条件,或者是数据遍历完,或者是条件限制不满足
4、递归前后的列数保持一致,数据类型保持一致

然后就是不同的数据库,对 CTE 使用的限制了,这个需要各位自己慢慢体会了。比如刚才提到,MySql 中,CTE 递归不能使用排名函数。之前老顾的文章中提到,MsSql CTE 递归中,不能使用关联,不能使用行转列之类的。

几个CTE 递归的示例

由于 MsSql 和 MySql 的基础查询都差不多,我就只写一个了,大家自行调整适配自己的环境即可。

阶乘

嗯,就是一个简单示例,因为数据库中有数据类型,整型范围较小,所以生成不了多少数据

with t as (
	select 1 id,convert(bigint,1) as p
	union all
	select id + 1,p * (id + 1) 
	from t
	where id <= 15
)
select * from t order by id

在这里插入图片描述

斐波那契序列

with t as (
	select 1 num,convert(bigint,1) n1,convert(bigint,1) n2
	union all
	select num + 1,n2,n1 + n2 
	from t where num<50
) 
select * from t

在这里插入图片描述

无限级分类路径

with t as (
	select 1 id,0 parent,'顶级分类1' name
	union all select 2,0,'顶级分类2'
	union all select 3,1,'大项1'
	union all select 4,2,'大项2'
	union all select 5,1,'大项3'
	union all select 6,3,'小项1'
	union all select 7,3,'小项2'
	union all select 8,5,'小项3'
	union all select 9,5,'小项4'
	union all select 10,7,'细项1'
	union all select 11,7,'细项2'
),t1 as (
	select *,convert(varchar(max),id) pth,convert(nvarchar(max),name) npth 
	from t
	where parent=0
	union ALL
	select a.*,pth + '|' + convert(varchar,a.id),npth + ' => ' + a.name
	from t a,t1 b
	where a.parent=b.id
) 
select * from t1 order by pth

在这里插入图片描述
这个算是比较常用的了,扩展一下,加上每个项的排序也生成一个路径,那么基本就可以当做最后的内容使用了,直接做成视图。

rand 函数

不管是 mysql还是mssql,随机函数都是 rand,我们可以用 select rand() 得到一个随机的浮点数。

但是,在这两个数据库中, rand 的表现不尽相同,例如,我们在刚才的 cte 生成的 100行数据里,加上 rand() 方法,看看最后的区别。

# MySql
with RECURSIVE t as (
	select 1 id
	union all
	select id + 1 
	from t
	where id < 100
)
select *,rand() from t
order by id

在这里插入图片描述
MySql一切正常,每行都有一个随机数。

在看 MsSql 的表现。

#MsSql
with t as (
	select 1 id
	union all
	select id + 1 
	from t
	where id < 100
)
select *,rand() from t order by id

在这里插入图片描述
这是见了鬼了,好在不管是 MySql 还是 MsSql 都可以对 rand 函数指定一个种子,我们可以先生成一次固定的100行数据。

#MySql
with RECURSIVE t as (
	select 1 id
	union all
	select id + 1 
	from t
	where id < 100
)
select *,rand(id) from t
order by id

#MsSql
with t as (
	select 1 id
	union all
	select id + 1 
	from t
	where id < 100
)
select *,rand(id * 10000) from t order by id

MySql 结果
在这里插入图片描述
MsSql 结果
在这里插入图片描述
当然,MsSql 可以使用 checksum 和 newid 来辅助生成真正的随机数,毕竟 newid 是可以跨行的随机序列。

那么,在有了随机数的情况下,我们就可以使用 cte 递归来生成一些数据,而不用通过循环、游标之类的方式了。

小结

本文主要介绍了 CTE 的一些基本知识点,在无限级分类示例中,可以看到 cte 可以多次定义,方便我们对数据进一步处理,当查询需求比较复杂时,可以做多一些CTE内容,将数据都处理好了之后,最后再用一个总的查询将结果输出。以这种方式,对比子查询方式,执行计划更稳定。

在数据库中建立视图的时候,我们无法使用临时表之类的东西,而 CTE 却不受限制,所以用好 CTE ,对一些比较复杂的查询做成视图是有很大帮助的。

如果小伙伴们还有什么比较有趣的 CTE 使用示例或方法,也请告知老顾哦。
在这里插入图片描述

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

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

相关文章

京东商品详情数据接口采集技术,支持整站数据高并发采集

一、如何通过手动方式查看京东商品详情页面的数据 1.京东商品详情 API 接口&#xff08;item_get - 获得京东商品详情接口&#xff09;&#xff0c;京东API 接口代码对接可以获取到宝贝 ID&#xff0c;宝贝标题&#xff0c;价格&#xff0c;优惠价&#xff0c;掌柜名称&…

节卡率先冲刺科创板,协作机器人商业化正当时

日前&#xff0c;上交所新增受理节卡机器人股份有限公司科创板上市申请&#xff0c;该公司拟募集资金7.5亿元&#xff0c;国泰君安任保荐人。此前&#xff0c;节卡机器人共完成6轮融资&#xff0c;总融资额超14亿元。按照最后的一轮融资计算&#xff0c;公司引入软银愿景基金二…

如何在云上部署java项目

最近博主接了一波私活&#xff0c;由于上云的概念已经深入人心&#xff0c;客户要求博主也上云&#xff0c;本文将介绍上云的教程。 1.如何选择服务器 这里博主推荐阿里云服务器&#xff0c;阿里云云服务器ECS是一种安全可靠、弹性可伸缩的云计算服务&#xff0c;助您降低 IT…

缓存三种方式

缓存能解决的问题 提升性能 绝大多数情况下&#xff0c;select 是出现性能问题最大的地方。一方面&#xff0c;select 会有很多像 join、group、order、like 等这样丰富的语义&#xff0c;而这些语义是非常耗性能的&#xff1b;另一方面&#xff0c;大多 数应用都是读多写少&…

阿里出版的这份Spring Security源码手册,狂揽GitHub榜首

写在前面 自从 Spring Boot、Spring Cloud 火起来之后&#xff0c;Spring Security 也跟着沾了一把光&#xff01; 其实我一直觉得 Spring Security 是一个比 Shiro 优秀很多的权限管理框架&#xff0c;但是重量级、配置繁琐、门槛高这些问题一直困扰着 Spring Security 的开…

【保姆级教程】如何用Rust编写一个ChatGPT桌面应用 | 京东云技术团队

为什么我们需要一个桌面应用 原因实在太多&#xff0c;我们需要便捷地导出记录&#xff0c;需要在回答长度超长的时候自动加上“继续”&#xff0c;需要收藏一些很酷很实用的prompt… &#xff08;首先我假设你是一名如我一样习惯用IDEA开发的java仔&#xff09; 为什么是用R…

孙鑫VC++第四章 1.简单绘图-MFC消息映射机制

1. MFC消息映射机制 接下来将剖析MFC消息映射机制&#xff0c;探讨发送给窗口的消息是如何被MFC框架通过窗口句柄映射表和消息映射表来用窗口类的处理函数进行响应的。另外&#xff0c;还将讲述“类向导”这一工具的运用&#xff0c;讨论设备描述表及其封装类CDC的使用&#x…

Javase06|类和对象

Javase06|类和对象 文章目录 Javase06|类和对象1.面向对象的初步认识2.类的定义3.类的实例化4.this引用5.对象的构造及初始化6.封装7.static成员8.代码块 1.面向对象的初步认识 1.1对象的概念 Java是一门面向对象的语言&#xff0c;面向对象主要依靠对象之间的交互完成一件事…

审稿意见相互矛盾的11种可能情况及修改建议

遇到相互矛盾的审稿意见&#xff0c;作者很难不纠结&#xff0c;毕竟哪个审稿人都不想得罪&#xff0c;到底该怎么办呢&#xff1f; 虽然有些审稿意见乍一看上去相互矛盾&#xff0c;但深思之后&#xff0c;也能发现其中的共性或者根本问题。明确了这一点&#xff0c;就比较清楚…

<六> objectARX开发:创建、插入、删除图块

1、介绍 所有的实体都保存在块表记录中,而块表记录则存储在块表中。实际上,用户在AutoCAD中定义块相当于增加了一个块表记录,块表记录的名称就是块定义的名称。打开任意dwg文件,然后创建两个从图中可以看出,当前图形的块表中包含了五个记录: *Model_Space、 Paper_Space、…

Qt--基于TCP客户端与服务器的聊天程序(半双工通信)

目录 任务&#xff1a;实现一个基于TCP的聊天程序&#xff0c;需要使用的类有&#xff1a; QTcpServer ​编辑 QTcpSocket ​编辑 QTextStream 服务端&#xff1a;server&#xff08;QTcpServer&#xff09; 步骤&#xff1a; 代码&#xff1a; dialog.h dialog.cpp 客户端&am…

论文笔记:基于手机位置信息的地图匹配算法

2015计算机应用 整体思路和论文笔记&#xff1a;Hidden Markov Map MatchingThrough Noise and Sparseness_UQI-LIUWJ的博客-CSDN博客 很像&#xff0c;也是应用HMM进行地图匹配 HMMM本文 状态转移矩阵 观测概率矩阵 正态分布均值都是0&#xff0c;唯一不同的是S…

统计学习方法第五章——决策树

x.1 决策树前言 decision tree决策树是一种分类和回归的方法&#xff0c;本章只考虑在分类领域的使用。决策树使用了归纳法划分特征空间&#xff0c;以此来达到分类的目的。决策树不同于KNN中的kd树&#xff0c;它是多叉树&#xff0c;不是二叉树。决策树是一种概率模型。 决…

毕业2年,月薪25k,有时候人与人的差距比人和狗还大···

想起两年前交流过的一个应届生&#xff0c;当时他刚毕业技术水平不高&#xff0c;进了一个小公司做测试实习工作。最近联系上了&#xff0c;不问不知道&#xff0c;一问吓一跳&#xff0c;他现在已经进了某一线大厂&#xff0c;月薪25K。这位朋友其实也没比别人强多少&#xff…

原神服务端架构搭建工具+环境配置资料

原神服务端架构搭建工具环境配置资料 我是艾西&#xff0c;今天给大家分享一份详细的原神服务端结构资料教程&#xff0c;从服务端的获取到端口的使用以及安卓和ios的DAIL签名等一文让你明白怎么架设原神服务端&#xff0c;哪些工具资料又代表着什么意思&#xff08;保姆级教学…

RFM模型

目录标题 定义指标分析模型分析如何衡量每个客户的RFM指标1. 确定时间范围2. 要定义指标的衡量标准3. 对客户指标进行打分4. 计算平均值5. 用户分类 不同客户不同解决方案 RFM的最大短板RFM的深层问题R&#xff1a;用户离得越久就越有流失风险F&#xff1a;用户频次越高越忠诚M…

SpringBoot 日志文件从入门到实战

文章目录 1. 日志的作用2. 日志怎么用3. 自定义日志打印3.1 程序中得到日志对象3.2 使用日志对象打印日志3.3 日志格式说明 4. 日志级别4.1 日志级别的作用4.2 日志级别的分类与使用4.3 日志级别的设置4.4 综合练习 5. 日志的持久化5.1 配置日志文件的保存路径:5.2 配置日志文件…

MVP发布后,下一步该怎么办

MVP发布后&#xff0c;下一步该怎么办 一、为什么要从发布MVP开始&#xff1f;二、发布MVP后该做什么&#xff1f;1、推广MVP2、收集用户反馈3、进行用户发展访谈4、确定功能的优先次序5、建立一个产品路线图 三、如何衡量一个MVP的成功&#xff1f;1、分析仪表板的重要性2、创…

图解LeetCode——160. 相交链表

一、题目 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中不存在环。注意&#xff0c;函数返回…

怎么把jfif改成png格式?这四种方法值得一试

怎么把JFIFf改成PNG格式&#xff1f;众所周知&#xff0c;JFIF是一种JPEG图像格式的子集&#xff0c;可以提供高质量的压缩效果。但是&#xff0c;JFIF格式有一些限制&#xff0c;例如它不支持透明度和多图层等功能&#xff0c;而PNG格式则是一种无损压缩的图像文件格式&#x…