MySQL8.0的WITH查询详情

目录
  • 关于MySQL8的WITH查询学习
    • 1、示例
    • 3、练习

关于MySQL8的WITH查询学习

前言:

对于逻辑复杂的sql,with可以大大减少临时表的数量,提升代码的可读性、可维护性
MySQL 8.0终于开始支持with语句了,对于复杂查询,可以不用写那么多的临时表了。
可以查看官方文档【点击跳转】

1、示例

官方第一个示例,可以看出该查询语句创建了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 ]

官方文档还列出了,使用临时表时可以增删改查新表,具体可以去阅读官方文档。

3、练习

关于递归的练习主要用于表里面包含父节点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,递归的将父节点数据放入临时表
最终查询出来的就是递归的结果。

到此这篇关于MySQL的WITH查询详情的文章就介绍到这了,更多相关MySQL的WITH查询内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • mysql视图之确保视图的一致性(with check option)操作详解

    本文实例讲述了mysql视图之确保视图的一致性(with check option)操作.分享给大家供大家参考,具体如下: 我们有的时候,会创建一个视图来显示表的部分数据.我们知道,简单视图是的,因此可以更新通过视图不可见的数据,但是此更新会使的视图不一致.为了确保视图的一致性,在创建或修改视图时使用WITH CHECK OPTION可更新子句.我们来看下WITH CHECK OPTION可更新子句的语法结构: CREATE OR REPLACE VIEW view_name AS select

  • MySQL 5.6 中TIMESTAMP with implicit DEFAULT value is deprecated错误

    安装MySQL时,有warning: [root@localhost mysql]# scripts/mysql_install_db --user=mysql Installing MySQL system tables...2015-08-13 14:20:09 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server

  • MySQL错误TIMESTAMP column with CURRENT_TIMESTAMP的解决方法

    在部署程序时遇到的一个问题,MySQL定义举例如下: 复制代码 代码如下: CREATE TABLE `example` (  `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,  `created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,  `lastUpdated` TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP,  PRIMARY KEY (`id`)

  • MySQL提示:The server quit without updating PID file问题的解决办法

    用df命令查了下,果然磁盘满了,因为当时分区采用系统默认,不知道为什么不能自动扩容!以后在处理这个问题!如图所示: 复制代码 代码如下: [root@snsgou ~]# df文件系统                 1K-块      已用      可用 已用% 挂载点/dev/mapper/vg_snsgou-lv_root51606140  47734848   1249852  100%      /tmpfs                  1953396        88  

  • php SQL Injection with MySQL

    前言 2003年开始,喜欢脚本攻击的人越来越多,而且研究ASP下注入的朋友也逐渐多了起来,我看过最早的关于SQL注入的文章是一篇99年国外的高手写的,而现在国外的已经炉火纯青了,国内才开始注意这个技术,由此看来,国内的这方面的技术相对于国外还是有一段很大差距,话说回来,大家对SQL注入攻击也相当熟悉了,国内各大站点都有些堪称经典的作品,不过作为一篇完整的文章,我觉得还是有必要再说说其定义和原理.如果哪位高手已经达到炉火纯青的地步,不妨给本文挑点刺.权当指点小弟. 关于php+Mysql的注入 国

  • MySql8 WITH RECURSIVE递归查询父子集的方法

    背景 开发过程中遇到类似评论的功能是,需要时用查询所有评论的子集.不同数据库中实现方式也不同,本文使用Mysql数据库,版本为8.0 Oracle数据库中可使用START [Param] CONNECT BY PRIOR Mysql 中需要使用 WITH RECURSIVE 需求 找到name为张三的孩子和孙子,pid为当前记录的父id,如张三儿子的pid为张三的id,以此类推. 引入 计算1到100的累加的结果. WITH RECURSIVE t(n) AS ( //t为我们结果表,n为字段,

  • 安装mysql出错”A Windows service with the name MySQL already exists.“如何解决

    如果以前安装过mysql,卸载重装,很可能会碰到"A Windows service with the name MySQL already exists."这样的提示.即服务已经存在. 我们可以在window任务管理器----服务中查看,发现确实存在,没有卸载干净. 解决这个问题,可以在dos窗口,使用如下命令: 复制代码 代码如下: sc delete mysql 如果成功,出现如下结果: [SC] DeleteService SUCCESS 之后,重启电脑.如果再在任务管理器--

  • MySQL8.0的WITH查询详情

    目录 关于MySQL8的WITH查询学习 1.示例 3.练习 关于MySQL8的WITH查询学习 前言: 对于逻辑复杂的sql,with可以大大减少临时表的数量,提升代码的可读性.可维护性 MySQL 8.0终于开始支持with语句了,对于复杂查询,可以不用写那么多的临时表了. 可以查看官方文档[点击跳转] 1.示例 官方第一个示例,可以看出该查询语句创建了cte1,cte2,cte3,cte4这4个临时表,后面的临时表依赖前面的临时表数据. 最后一行为最终查询结果,实际ct4因为ct3结果包含

  • MySQL8.0 索引优化invisible index详情

    目录 前言 索引使用情况测试 如何临时让优化器可以看到这个索引呢? 修改索引的可见性 前言 MySQL8.0 开始支持不可见索引. 优化器根本不使用不可见索引,但会以其他的方式正常维护. 默认情况下 索引是可见的. 通过不可见索引,可以方便数据库管理人员 检查 索引对查询性能的影响,而不会进行破坏性的更改 . 应用场景: 软删除,灰度发布 -- 创建测试表 mysql> create table t1(i int ,j int); Query OK, 0 rows affected (0.03

  • MySQL8.0内存相关参数总结

    MySQL理论上使用的内存 = 全局共享内存 + max_connections×线程独享内存. 也就是:innodb_buffer_pool_size + innodb_log_buffer_size + thread_cache_size +table_open_cache + table_definition_cache +key_buffer_size + max_connections *( thread_stack+ sort_buffer_size+join_buffer_size

  • mysql8.0.23 linux(centos7)安装完整超详细教程

    上篇文章给大家介绍了MySQL 8.0.23 主要更新一览(新特征解读) ,感兴趣的朋友点击查看吧! 最新版windows mysql-8.0.23-winx64,点击下载 mysql8.0.23 linux(centos7)安装教程(附:配置外网连接用户授权 与 不区分大小写配置) (博主在这里叨叨几句,稍后进入正题.在使用开发过程中,有时候数据库结合使用,会成倍提高程序效率) 什么是关系型数据库? 常见的关系型数据库: (其实博主也只使用过 MySQL Oracle sqlServer) O

  • mysql-8.0.11-winx64.zip安装教程详解

    下载zip安装包: MySQL8.0 For Windows zip包下载地址:https://dev.mysql.com/downloads/file/?id=476233,进入页面后可以不登录.后点击底部"No thanks, just start my download."即可开始下载. 或直接下载:https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.11-winx64.zip 环境:Windows 10 一,安装 1.

  • mysql8.0.11 winx64手动安装配置教程

    首先跟大家唠一唠家常,随着MySQL迅速的更新,MySQL突飞猛进已经更新到了8.0版本,那么它和我们之前用的5.X版本有什么明显的区别那?首先给大家看下MySQL5.X自带表的查询速度 之后献上MySQL8.0的自带表的查询速度 一样的数据结果显而易见,MySQL8.0的坑我是走了个遍,为了让大家少走弯路,献上以下手动安装方法 1. 官网下载并解压 我下载了mysql-8.0.11-winx64,下载地址 直接点击我红色记号笔圈出的超链接,这句话的中文意思是:不用了,直接开始下载 2. 设置系

  • mysql8.0.11 winx64安装配置方法图文教程(win10)

    mysql 8.0.11 winx64安装教程记录如下,分享给大家 1.进入地址: 下载mysql-8.0.11-winx64 2.解压zip包,并将解压文件放入一个文件夹下,如图: 3.配置环境变量(目的是为了避免在CMD窗口下操作时反复切换路径) 在Path下添加 D:\Program Files\mysql-8.0.11-winx64\bin 4.编写配置文件 我们发现解压后的目录并没有my.ini(或my-default.ini)文件,没关系可以自行创建.在安装根目录下添加 my.ini

  • MySQL8.0.11版本的新增特性介绍

    MySQL 8.0 for Windows v8.0.11 官方免费正式版 64位 一. 数据字典(Data dictionary) 1)合并了存储数据库对象信息的事务性数据字典:之前版本是存储于元数据文件和非事务表中 : 二.原子数据定义语句(原子DDL)(Atomic Data Definition Statements (Atomic DDL)) 三.安全性和账户管理(Security and account management) 1)A new caching_sha2_passwor

  • mysql-8.0.17-winx64 部署方法

    1.官网下载mysql-8.0.17-winx64,选择Zip文件格式下载 2.解压到目标路径,我这里是E盘根目录,即E:\mysql8 3.根目录下创建my.ini,内容如下: [mysqld] #端口 port = 3306 #mysql安装目录 basedir = E:/mysql8 #mysql数据存放目录 datadir = E:/mysql8/data #允许最大连接数 max_connections = 1024 #服务端默认使用字符集 character-set-server =

  • 浅析CentOS6.8安装MySQL8.0.18的教程(RPM方式)

    今天,记录下在CentOS 6.8服务器上如何安装MySQL 8.0.18,废话不多说了,直接进入主题. 一.卸载CentOS 6.8自带的MySQL 首先,卸载CentOS 6.8服务器上自带的MySQL,在命令行中输入如下命令查看CentOS 6.8服务器自带的MySQL. [root@binghe151 src]# rpm -qa | grep -i mysql mysql-libs-5.1.73-7.el6.x86_64 可以看到,CentOS 6.8服务器中默认安装了mysql-lib

随机推荐