温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

MySQL的with语句怎么使用

发布时间:2022-11-14 10:04:15 来源:亿速云 阅读:160 作者:iii 栏目:开发技术

本文小编为大家详细介绍“MySQL的with语句怎么使用”,内容详细,步骤清晰,细节处理妥当,希望这篇“MySQL的with语句怎么使用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

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

对于逻辑复杂的sql,with可以大大减少临时表的数量,提升代码的可读性、可维护性

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

语句结构:

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语句怎么使用”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI