MySQL with语句讲解

目录
  • 一.提升代码的可读性和可维护性
  • 二.with递归

备注:测试数据库版本为MySQL 8.0

今天我们来聊聊MySQL的with语句
对于逻辑复杂的sql,with可以大大减少临时表的数量,提升代码的可读性、可维护性

MySQL 8.0终于开始支持with语句了,对于复杂查询,可以不用写那么多的临时表了。

如需要scott用户下建表及录入数据语句,可参考:
scott建表及录入数据sql脚本

语句结构:

with subquery_name1 as (subquery_body1),
        subquery_name2 as (subquery_body2)
...
select * from subquery_name1 a, subquery_name2 b
where a.col = b.col
...

优势

  • – 代码模块化
  • – 代码可读性增强
  • – 相同查询唯一化

一.提升代码的可读性和可维护性

需求:求每个部门的平均工资,以及剔除薪资低于1000的实习人员之后的平均工资

-- 求每个部门的平均工资,以及剔除薪资低于1000的实习人员之后的平均工资
-- 主查询的from后面跟了2个临时表,程序可读性不佳
select d.deptno, tmp1.avg_sal avg_sal1, tmp2.avg_sal avg_sal2
  from dept d
  left join (select e1.deptno, round(avg(ifnull(e1.sal, 0)), 2) avg_sal
               from emp e1
              group by e1.deptno) tmp1
    on d.deptno = tmp1.deptno
  left join (select e1.deptno, round(avg(ifnull(e1.sal, 0)), 2) avg_sal
               from emp e1
              where e1.sal > 1000
              group by e1.deptno) tmp2
    on d.deptno = tmp2.deptno;

-- 求每个部门的平均工资,以及剔除薪资低于1000的实习人员之后的平均工资
-- 2个临时表的定时语句通过with封装成子查询了,程序可读性增强
with tmp1 as
 (select e1.deptno, round(avg(ifnull(e1.sal, 0)), 2) avg_sal
    from emp e1
   group by e1.deptno),
tmp2 as
 (select e1.deptno, round(avg(ifnull(e1.sal, 0)), 2) avg_sal
    from emp e1
   where e1.sal > 1000
   group by e1.deptno)
select d.deptno, tmp1.avg_sal avg_sal1, tmp2.avg_sal avg_sal2
  from dept d
  left join tmp1
    on d.deptno = tmp1.deptno
  left join tmp2
    on d.deptno = tmp2.deptno;
mysql> -- 求每个部门的平均工资,以及剔除薪资低于1000的实习人员之后的平均工资
mysql> -- 主查询的from后面跟了2个临时表,程序可读性不佳
mysql> select d.deptno, tmp1.avg_sal avg_sal1, tmp2.avg_sal avg_sal2
    ->   from dept d
    ->   left join (select e1.deptno, round(avg(ifnull(e1.sal, 0)), 2) avg_sal
    ->                from emp e1
    ->               group by e1.deptno) tmp1
    ->     on d.deptno = tmp1.deptno
    ->   left join (select e1.deptno, round(avg(ifnull(e1.sal, 0)), 2) avg_sal
    ->                from emp e1
    ->               where e1.sal > 1000
    ->               group by e1.deptno) tmp2
    ->     on d.deptno = tmp2.deptno;
+--------+----------+----------+
| deptno | avg_sal1 | avg_sal2 |
+--------+----------+----------+
|     10 |  2916.67 |  2916.67 |
|     20 |  2175.00 |  2518.75 |
|     30 |  1566.67 |  1690.00 |
|     40 |     NULL |     NULL |
+--------+----------+----------+
4 rows in set (0.00 sec)

mysql>
mysql>
mysql> -- 求每个部门的平均工资,以及剔除薪资低于1000的实习人员之后的平均工资
mysql> -- 2个临时表的定时语句通过with封装成子查询了,程序可读性增强
mysql> with tmp1 as
    ->  (select e1.deptno, round(avg(ifnull(e1.sal, 0)), 2) avg_sal
    ->     from emp e1
    ->    group by e1.deptno),
    -> tmp2 as
    ->  (select e1.deptno, round(avg(ifnull(e1.sal, 0)), 2) avg_sal
    ->     from emp e1
    ->    where e1.sal > 1000
    ->    group by e1.deptno)
    -> select d.deptno, tmp1.avg_sal avg_sal1, tmp2.avg_sal avg_sal2
    ->   from dept d
    ->   left join tmp1
    ->     on d.deptno = tmp1.deptno
    ->   left join tmp2
    ->     on d.deptno = tmp2.deptno;
+--------+----------+----------+
| deptno | avg_sal1 | avg_sal2 |
+--------+----------+----------+
|     10 |  2916.67 |  2916.67 |
|     20 |  2175.00 |  2518.75 |
|     30 |  1566.67 |  1690.00 |
|     40 |     NULL |     NULL |
+--------+----------+----------+
4 rows in set (0.00 sec)

mysql>

二.with递归

用with递归构造数列

-- 用with递归构造1-10的数据
with RECURSIVE c(n) as
 (select 1   union all select n + 1 from c where n < 10)
select n from c;
-- 用with递归构造1-10的数据
mysql> with RECURSIVE c(n) as
    ->  (select 1   union all select n + 1 from c where n < 10)
    -> select n from c;
+------+
| n    |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
|    5 |
|    6 |
|    7 |
|    8 |
|    9 |
|   10 |
+------+
10 rows in set (0.00 sec)

用with递归构造级联关系

with RECURSIVE emp2(ename,empno,mgr,lvl)
  as
   (select ename, empno, mgr, 1 lvl from emp where mgr is null
    union all
    select emp.ename, emp.empno, emp.mgr, e2.lvl+1
      from emp, emp2 e2
     where emp.mgr = e2.empno
   )
select lvl,
      concat(repeat('**',lvl),ename) nm
  from emp2
 order by lvl,ename
;
mysql> with RECURSIVE emp2(ename,empno,mgr,lvl)
    ->   as
    ->    (select ename, empno, mgr, 1 lvl from emp where mgr is null
    ->     union all
    ->     select emp.ename, emp.empno, emp.mgr, e2.lvl+1
    ->       from emp, emp2 e2
    ->      where emp.mgr = e2.empno
    ->    )
    -> select lvl,
    ->       concat(repeat('**',lvl),ename) nm
    ->   from emp2
    ->  order by lvl,ename
    -> ;
+------+---------------+
| lvl  | nm            |
+------+---------------+
|    1 | **KING        |
|    2 | ****BLAKE     |
|    2 | ****CLARK     |
|    2 | ****JONES     |
|    3 | ******ALLEN   |
|    3 | ******FORD    |
|    3 | ******JAMES   |
|    3 | ******MARTIN  |
|    3 | ******MILLER  |
|    3 | ******SCOTT   |
|    3 | ******TURNER  |
|    3 | ******WARD    |
|    4 | ********ADAMS |
|    4 | ********SMITH |
+------+---------------+
14 rows in set (0.00 sec)

到此这篇关于MySQL with语句小结的文章就介绍到这了,更多相关mysql with语句内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Mysql中通用表达式WITH AS语句的使用实例代码

    目录 一.WITH AS 的含义 二.WITH AS 的含使用 三.WITH AS 的作用 补充:使用with as应该注意 总结 一.WITH AS 的含义 使用with as 可以让子查询重用相同的with查询块,并在select查询块中直接引用,一般用在select查询块会多次使用某个查询sql时,会把这个sql语句放在with as 中,作为公用的表达式,通过别名的方式在主查询语句中重复使用. 二.WITH AS 的含使用 现有两张表cust_info_detail(客户信息表,表中三个

  • MySQL with语句讲解

    目录 一.提升代码的可读性和可维护性 二.with递归 备注:测试数据库版本为MySQL 8.0 今天我们来聊聊MySQL的with语句对于逻辑复杂的sql,with可以大大减少临时表的数量,提升代码的可读性.可维护性 MySQL 8.0终于开始支持with语句了,对于复杂查询,可以不用写那么多的临时表了. 如需要scott用户下建表及录入数据语句,可参考:scott建表及录入数据sql脚本 语句结构: with subquery_name1 as (subquery_body1), subqu

  • python 3.6 +pyMysql 操作mysql数据库(实例讲解)

    版本信息:python:3.6 mysql:5.7 pyMysql:0.7.11 ################################################################# #author: 陈月白 #_blogs: http://www.cnblogs.com/chenyuebai/ ################################################################# # -*- coding: utf-8

  • spark rdd转dataframe 写入mysql的实例讲解

    dataframe是在spark1.3.0中推出的新的api,这让spark具备了处理大规模结构化数据的能力,在比原有的RDD转化方式易用的前提下,据说计算性能更还快了两倍.spark在离线批处理或者实时计算中都可以将rdd转成dataframe进而通过简单的sql命令对数据进行操作,对于熟悉sql的人来说在转换和过滤过程很方便,甚至可以有更高层次的应用,比如在实时这一块,传入kafka的topic名称和sql语句,后台读取自己配置好的内容字段反射成一个class并利用出入的sql对实时数据进行

  • 详解mysql DML语句的使用

    前言: 在上篇文章中,主要为大家介绍的是DDL语句的用法,可能细心的同学已经发现了.本篇文章将主要聚焦于DML语句,为大家讲解表数据相关操作. 这里说明下DDL与DML语句的分类,可能有的同学还不太清楚. DDL(Data Definition Language):数据定义语言,用于创建.删除.修改.库或表结构,对数据库或表的结构操作.常见的有create,alter,drop等. DML(Data Manipulation Language):数据操纵语言,主要对表记录进行更新(增.删.改).

  • Mysql超详细讲解死锁问题的理解

    目录 1.什么是死锁? 2.Mysql出现死锁的必要条件 资源独占条件 请求和保持条件 不剥夺条件 相互获取锁条件 3. Mysql经典死锁案例 3.1 建表语句 3.2 初始化相关数据 3.3 正常转账过程 3.4 死锁转账过程 3.5 死锁导致的问题 4.如何解决死锁问题? 4.1 打破请求和保持条件 4.2 打破相互获取锁条件(推荐) 5.总结 1.什么是死锁? 死锁指的是在两个或两个以上不同的进程或线程中,由于存在共同资源的竞争或进程(或线程)间的通讯而导致各个线程间相互挂起等待,如果没

  • MySQL 案例分析讲解外连接语法

    目录 前言 左连接 例 1 右连接 例2 作业记录 前言 外连接可以分为左外连接和右外连接 左外连接: 包含左边表的全部行(不管右边的表中是否存在与它们匹配的行),以及右边表中全部匹配的行 右外连接: 包含右边表的全部行(不管左边的表中是否存在与它们匹配的行),以及左边表中全部匹配的行 左连接 左外连接又称为左连接,使用 LEFT OUTER JOIN 关键字连接两个表,并使用 ON 子句来设置连接条件. 左连接的语法格式如下: SELECT <字段名> FROM <表1> LEF

  • mysql详细分析讲解子查询的使用

    出现在其他语句中的 select 语句,称为子查询或内查询:外部的查询语句,称为主查询或 外查询 . -- 子查询 -- 查询的条件来自于另一查询的结果 SELECT * FROM t_user WHERE number=(SELECT number FROM t_user WHERE NAME='张三') 当然子查询也有类型,分为以下几种 : 标量子查询(结果集只有一行一列) 列子查询(结果集只有一列多行) 行子查询(结果集有一行多列)(较少) 表子查询(结果集一般为多行多列) 这里我们以新建

  • MySQL数据处理梳理讲解增删改的操作

    目录 一.插入数据 VALUES的方式添加 为表的所有字段按默认顺序插入数据 为表的指定字段插入数据 同时插入多条记录 将查询结果插入到表中 二.更改数据(更新) 三.删除数据 一.插入数据 VALUES的方式添加 使用一次只能向表中插入一条数据 为表的所有字段按默认顺序插入数据 INSERT INTO 表名VALUES (value1,value2,....); 值列表中须为表的每一个字段指定值 值的顺序必须和数据表中字段定义时的顺序相同 为表的指定字段插入数据 INSERT INTO 表名(

  • MySql超详细讲解表的用法

    目录 1. 建表的语法 2. mysql中的数据类型 3. 模拟表 4. 创建一个学生表 1. 创建表(create-DDL) 2. 插入数据(insert-DML) 3. 插入日期 4. date和datetime的区别 5. 更新(update-DML) 6. 删除(delete-DML) 5. 快速创建表(复制表) 6. 快速删除表中数据 1. 建表的语法 建表属于 DDL 语句,DDL 语句包括:create.drop.alter… create table 表名(字段1 数据类型, 字

  • mysql查询语句中用户变量的使用代码解析

    上一篇文章中我们介绍了MySQL优化总结-查询总条数.这篇文章我们来介绍下查询语句中的另一个知识:用户变量的使用代码解析. 先上代码吧 SELECT `notice`.`id` , `notice`.`fid` , `notice`.`has_read` , `notice`.`notice_time` , `notice`.`read_time` , `f`.`fnum` , `f`.`forg` , `f`.`fdst` , `f`.`actual_parking` AS `parking`

随机推荐