关于MySQL8的WITH查询学习
前言
对于逻辑复杂的sql,with可以大大减少临时表的数量,提升代码的可读性、可维护性
MySQL 8.0终于开始支持with语句了,对于复杂查询,可以不用写那么多的临时表了。
可以查看官方文档【点击跳转】
示例
官方第一个示例,可以看出该查询语句创建了cte1
,cte2
,cte3
,cte4
这4个临时表,后面的临时表依赖前面的临时表数据。
最后一行为最终查询结果,实际ct4
因为ct3
结果包含3行数据,但是使用MAX
,MIN
得到一行结果。
WITH cte1(txt) AS (SELECT "This "),
cte2(txt) AS (SELECT CONCAT(cte1.txt,"is a ") FROM cte1),
cte3(txt) AS (SELECT "nice query" UNION
SELECT "query that rocks" UNION
SELECT "query"),
cte4(txt) AS (SELECT concat(cte2.txt, cte3.txt) FROM cte2, cte3)
SELECT MAX(txt), MIN(txt) FROM cte4;
+----------------------------+----------------------+
| MAX(txt) | MIN(txt) |
+----------------------------+----------------------+
| This is a query that rocks | This is a nice query |
+----------------------------+----------------------+
1 row in set (0,00 sec)
官方第二个示例是递归的用法,根据阅读文档,我分析下面查询结果如下。
首先定义一个临时表my_cte
分析SELECT 1 AS n
,这个是决定临时表的列名为n,值为1
然后SELECT 1+n FROM my_cte WHERE n<10
,这个是递归查询n<10
,并将1+n
作为结果填充临时表
最终使用SELECT * FROM my_cte
,查询临时表,因此查询出的结果就显而易见了
WITH RECURSIVE my_cte AS
(
SELECT 1 AS n
UNION ALL
SELECT 1+n FROM my_cte WHERE n<10
)
SELECT * FROM my_cte;
+------+
| n |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
| 10 |
+------+
10 rows in set (0,00 sec)
根据我的理解写了如下2个不一样的查询,查询结果都一样。
值得注意的是临时表里面的多个查询列数量和类型必须一样,不然会报错。
这个是将临时表列名指定在第一行
WITH RECURSIVE my_cte(a,b,c) AS
(
SELECT 1,1,1
UNION ALL
SELECT 1+a,2+b,3+c FROM my_cte WHERE a<10
)
SELECT * FROM my_cte;
这个第一行没有指定列名,然后列名由第一个查询返回结果确定
WITH RECURSIVE my_cte AS
(
SELECT 1 AS a,1 AS b,1 AS c
UNION ALL
SELECT 1+a,2+b,3+c FROM my_cte WHERE a<10
)
SELECT * FROM my_cte;
根据官方文档,临时表的语法模板如下,是可以有很多行的查询共同组成。
WITH RECURSIVE cte_name [list of column names ] AS
(
SELECT ... <-- specifies initial set
UNION ALL
SELECT ... <-- specifies initial set
UNION ALL
...
SELECT ... <-- specifies how to derive new rows
UNION ALL
SELECT ... <-- specifies how to derive new rows
...
)
[, any number of other CTE definitions ]
官方文档还列出了,使用临时表时可以增删改查新表,具体可以去阅读官方文档。
练习
关于递归的练习主要用于表里面包含父节点id之类的,详情可以参考下面的练习。
定义下面这样的表,存储每个区域(省、市、区)的id,名字及上级区域的pid
CREATE TABLE tb(id VARCHAR(3), pid VARCHAR(3), name VARCHAR(64));
INSERT INTO tb VALUES('002', 0, '浙江省');
INSERT INTO tb VALUES('001', 0, '广东省');
INSERT INTO tb VALUES('003', '002', '衢州市');
INSERT INTO tb VALUES('004', '002', '杭州市');
INSERT INTO tb VALUES('005', '002', '湖州市');
INSERT INTO tb VALUES('006', '002', '嘉兴市');
INSERT INTO tb VALUES('007', '002', '宁波市');
INSERT INTO tb VALUES('008', '002', '绍兴市');
INSERT INTO tb VALUES('009', '002', '台州市');
INSERT INTO tb VALUES('010', '002', '温州市');
INSERT INTO tb VALUES('011', '002', '丽水市');
INSERT INTO tb VALUES('012', '002', '金华市');
INSERT INTO tb VALUES('013', '002', '舟山市');
INSERT INTO tb VALUES('014', '004', '上城区');
INSERT INTO tb VALUES('015', '004', '下城区');
INSERT INTO tb VALUES('016', '004', '拱墅区');
INSERT INTO tb VALUES('017', '004', '余杭区');
INSERT INTO tb VALUES('018', '011', '金东区');
INSERT INTO tb VALUES('019', '001', '广州市');
INSERT INTO tb VALUES('020', '001', '深圳市');
WITH RECURSIVE cte AS (
SELECT id,name FROM tb WHERE id='002'
UNION ALL
SELECT k.id, CONCAT(c.name,'->',k.name) AS name FROM tb k INNER JOIN cte c ON c.id = k.pid
) SELECT * FROM cte;
执行结果:
分析结果包含第一行SELECT id,name FROM tb WHERE id='002'
的数据,此时表中只有一行数据
然后连表查询SELECT k.id, CONCAT(c.name,'->',k.name) AS name FROM tb k INNER JOIN cte c ON c.id = k.pid
,递归的将父节点数据放入临时表
最终查询出来的就是递归的结果。
总结
通过阅读官方文档,我知道了
WITH
查询是为了避免出现嵌套的子查询,每个查询结果都可以是一个临时表,然后总查询可以用到所有临时表的数据。
然后就是递归查询,可以解决树形接口的情况,数据有父子层级的那种。
关于MySQL8的WITH查询学习的更多相关文章
- Drools 查询学习
Drools 查询学习查询以 query 关键字开始,以 end 关键字结束,在 package 当中一个查询要有唯一的名称,查询的内容就是查询的条件部分,条件部分内容的写法与规则的 LHS 部分写法 ...
- Mysql查询——学习阶段
1.开篇 搞开发的都知道,当数据量很大的时候,我们的代码逻辑的简单性就显得十分重要,否则处理起来就需要花费相当多的时间.另外还有一个地方需要注意的是我们写的sql语句. 一个拥有多年开发的资深开发者可 ...
- MVC中使用Entity Framework 基于方法的查询学习笔记 (三)
紧接上文,我们已经学习了MVC数据上下文中两个常用的类,这两个类承载着利用函数方式进行数据查询的全部内容,我们既然已经了解了DbSet<TEntity> 是一个泛型集合,并且实现了一些接口 ...
- MVC中使用Entity Framework 基于方法的查询学习笔记 (一)
EF中基于方法的查询方式不同于LINQ和以往的ADO.NET,正因为如此,有必要深入学习一下啦.闲话不多说,现在开始一个MVC项目,在项目中临床学习. 创建MVC项目 1.“文件”--“新建项目”-- ...
- sql查询学习和实践点滴积累
https://blog.rjmetrics.com/2008/10/28/correlated-subqueries-in-mysql/ http://www.mysqltutorial.org/m ...
- MySQL8:连接查询
连接查询 连接是关系型数据库模型的主要特点. 连接查询是关系型数据库中最主要的查询,主要包括内连接.外连接等通过联结运算符可以实现多个表查询. 在关系型数据库管理系统中,表建立时各种数据之间的关系不必 ...
- MVC中使用Entity Framework 基于方法的查询学习笔记 (二)
解释,不解释: 紧接上文,我们在Visual Studio2012中看到系统为我们自动创建的视图(View)文件Index.cshtml中,开头有如下这句话: @model IEnumerable&l ...
- .NET系列文章——近一年文章分类整理,方便各位博友们查询学习
由于博主今后一段时间可能会很忙(准备出书:<.NET框架设计—模式.配置.工具>,外加换了新工作),所以博客会很少更新: 在最近一年左右时间里,博主各种.NET技术类型的文章都写过,根据博 ...
- MySQL 多表查询 学习与练习
一.介绍 首先先准备表 员工表和部门表 #建表 create table department( id int, name varchar(20) ); create table employee1( ...
随机推荐
- Centos ulimit设置
1.三处配置 1. 系统编译时默认设置文件(centos7新增) 服务配置 /etc/systemd/system.conf 用户配置 /etc/systemd/user.conf 2. PAM模块配 ...
- nginx服务跳转
1.什么是页面跳转 将URL信息做改变 将URI信息做改变 完成伪静态配置 2.实现页面跳转的方法 http://nginx.org/en/docs/http/ngx_http_rewrite_mod ...
- WebSocket实现前后端通讯
WebSocket实现前后端通讯 长安如梦里,何日是归期. 简介:我们上线了一个商城项目,移交运营团队使用之后,他们要求商城有新订单来的时候同时加上声音提示,让她们可以及时知道有单来了.我这边想了想, ...
- CRM系统对管理客户的帮助
我们可以把客户关系看做是一种长期的投资,在资源有限的基础上,把人力财力物力放到那些能够持续创造价值的客户身上,从而为企业带来源源不断的收益.通过进行客户关系管理,能够让企业与客户之间建立沟通的渠道,形 ...
- linux学习之路第九天(任务调度)
crond 任务调度 概念 任务调度:是指的系统在某个时间执行的特定命令或程序. 比喻理解: 可以这样理解,比如生活中有闹钟,闹钟的作用是不是叫人起床的,那古时候没有闹钟,叫人起床的工作是不是要人去完 ...
- linux:mysql
数据库介绍 mysql与php是黄金搭档(LAMP.LNMP) 常见的数据库 Oracle.Sql server.Access.Mariadb.Ds2等 安装 安装前确保计算机时间准确 源码包安装 优 ...
- ELK处理Spring Boot 日志,妙!
在排查线上异常的过程中,查询日志总是必不可缺的一部分.现今大多采用的微服务架构,日志被分散在不同的机器上,使得日志的查询变得异常困难. 工欲善其事,必先利其器.如果此时有一个统一的实时日志分析平台,那 ...
- 从零开始给女朋友讲计算机 1 - 从比特、字节、补码到 ASCII、GB2312、Unicode
起因 在代码 review 的过程中,总是发现有人在数据类型转换(reinterpret_cast).大小端的问题(什么情况下需要考虑大小端,什么情况下不需要考虑)上犯错误,究其原因是没有彻彻底底地搞 ...
- 物理机连接虚拟机中的数据库及Windows添加防火墙允许端口详细操作步骤
公司项目中因为会使用到SQL server数据库,但是自己电脑无论安装2008R2或者2014版本都不成功,我想可能是和之前安装的一些Windows的软件存在冲突. 于是便单独创建了一台虚拟机,在虚拟 ...
- 麒麟操作系统上安装docker并加载镜像
最近需要在政务云系统中部署深度学习环境,其使用麒麟操作系统并与互联网相互隔离,无法使用常规的指令行方式进行安装.参考docker官方文档并经过多次尝试,使用离线安装的方式完成了环境的部署.这里做一下笔 ...