MySQL with语句小结

缺乏、安全感 2022-11-19 04:23 308阅读 0赞

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

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

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

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

语句结构:

  1. with subquery_name1 as (subquery_body1),
  2. subquery_name2 as (subquery_body2)
  3. ...
  4. select * from subquery_name1 a, subquery_name2 b
  5. where a.col = b.col
  6. ...

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

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

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

  1. -- 求每个部门的平均工资,以及剔除薪资低于1000的实习人员之后的平均工资
  2. -- 主查询的from后面跟了2个临时表,程序可读性不佳
  3. select d.deptno, tmp1.avg_sal avg_sal1, tmp2.avg_sal avg_sal2
  4. from dept d
  5. left join (select e1.deptno, round(avg(ifnull(e1.sal, 0)), 2) avg_sal
  6. from emp e1
  7. group by e1.deptno) tmp1
  8. on d.deptno = tmp1.deptno
  9. left join (select e1.deptno, round(avg(ifnull(e1.sal, 0)), 2) avg_sal
  10. from emp e1
  11. where e1.sal > 1000
  12. group by e1.deptno) tmp2
  13. on d.deptno = tmp2.deptno;
  14. -- 求每个部门的平均工资,以及剔除薪资低于1000的实习人员之后的平均工资
  15. -- 2个临时表的定时语句通过with封装成子查询了,程序可读性增强
  16. with tmp1 as
  17. (select e1.deptno, round(avg(ifnull(e1.sal, 0)), 2) avg_sal
  18. from emp e1
  19. group by e1.deptno),
  20. tmp2 as
  21. (select e1.deptno, round(avg(ifnull(e1.sal, 0)), 2) avg_sal
  22. from emp e1
  23. where e1.sal > 1000
  24. group by e1.deptno)
  25. select d.deptno, tmp1.avg_sal avg_sal1, tmp2.avg_sal avg_sal2
  26. from dept d
  27. left join tmp1
  28. on d.deptno = tmp1.deptno
  29. left join tmp2
  30. on d.deptno = tmp2.deptno;
  31. mysql> -- 求每个部门的平均工资,以及剔除薪资低于1000的实习人员之后的平均工资
  32. mysql> -- 主查询的from后面跟了2个临时表,程序可读性不佳
  33. mysql>
  34. select d.deptno, tmp1.avg_sal avg_sal1, tmp2.avg_sal avg_sal2
  35. from dept d
  36. left join (select e1.deptno, round(avg(ifnull(e1.sal, 0)), 2) avg_sal
  37. from emp e1
  38. group by e1.deptno) tmp1
  39. on d.deptno = tmp1.deptno
  40. left join (select e1.deptno, round(avg(ifnull(e1.sal, 0)), 2) avg_sal
  41. from emp e1
  42. where e1.sal > 1000
  43. group by e1.deptno) tmp2
  44. on d.deptno = tmp2.deptno;
  45. +--------+----------+----------+
  46. | deptno | avg_sal1 | avg_sal2 |
  47. +--------+----------+----------+
  48. | 10 | 2916.67 | 2916.67 |
  49. | 20 | 2175.00 | 2518.75 |
  50. | 30 | 1566.67 | 1690.00 |
  51. | 40 | NULL | NULL |
  52. +--------+----------+----------+
  53. 4 rows in set (0.00 sec)
  54. mysql>
  55. mysql>
  56. mysql> -- 求每个部门的平均工资,以及剔除薪资低于1000的实习人员之后的平均工资
  57. mysql> -- 2个临时表的定时语句通过with封装成子查询了,程序可读性增强
  58. mysql>
  59. with tmp1 as
  60. (select e1.deptno, round(avg(ifnull(e1.sal, 0)), 2) avg_sal
  61. from emp e1
  62. group by e1.deptno),
  63. tmp2 as
  64. (select e1.deptno, round(avg(ifnull(e1.sal, 0)), 2) avg_sal
  65. from emp e1
  66. where e1.sal > 1000
  67. group by e1.deptno)
  68. select d.deptno, tmp1.avg_sal avg_sal1, tmp2.avg_sal avg_sal2
  69. from dept d
  70. left join tmp1
  71. on d.deptno = tmp1.deptno
  72. left join tmp2
  73. on d.deptno = tmp2.deptno;
  74. +--------+----------+----------+
  75. | deptno | avg_sal1 | avg_sal2 |
  76. +--------+----------+----------+
  77. | 10 | 2916.67 | 2916.67 |
  78. | 20 | 2175.00 | 2518.75 |
  79. | 30 | 1566.67 | 1690.00 |
  80. | 40 | NULL | NULL |
  81. +--------+----------+----------+
  82. 4 rows in set (0.00 sec)
  83. mysql>

二.with递归

用with递归构造数列

  1. -- with递归构造1-10的数据
  2. with RECURSIVE c(n) as
  3. (select 1 union all select n + 1 from c where n < 10)
  4. select n from c;
  5. -- with递归构造1-10的数据
  6. mysql>
  7. with RECURSIVE c(n) as
  8. (select 1 union all select n + 1 from c where n < 10)
  9. select n from c;
  10. +------+
  11. | n |
  12. +------+
  13. | 1 |
  14. | 2 |
  15. | 3 |
  16. | 4 |
  17. | 5 |
  18. | 6 |
  19. | 7 |
  20. | 8 |
  21. | 9 |
  22. | 10 |
  23. +------+
  24. 10 rows in set (0.00 sec)
  25. with RECURSIVE emp2(ename,empno,mgr,lvl)
  26. as
  27. (select ename, empno, mgr, 1 lvl from emp where mgr is null
  28. union all
  29. select emp.ename, emp.empno, emp.mgr, e2.lvl+1
  30. from emp, emp2 e2
  31. where emp.mgr = e2.empno
  32. )
  33. select lvl,
  34. concat(repeat('**',lvl),ename) nm
  35. from emp2
  36. order by lvl,ename
  37. ;
  38. mysql>
  39. with RECURSIVE emp2(ename,empno,mgr,lvl)
  40. as
  41. (select ename, empno, mgr, 1 lvl from emp where mgr is null
  42. union all
  43. select emp.ename, emp.empno, emp.mgr, e2.lvl+1
  44. from emp, emp2 e2
  45. where emp.mgr = e2.empno
  46. )
  47. select lvl,
  48. concat(repeat('**',lvl),ename) nm
  49. from emp2
  50. order by lvl,ename
  51. ;
  52. +------+---------------+
  53. | lvl | nm |
  54. +------+---------------+
  55. | 1 | **KING |
  56. | 2 | ****BLAKE |
  57. | 2 | ****CLARK |
  58. | 2 | ****JONES |
  59. | 3 | ******ALLEN |
  60. | 3 | ******FORD |
  61. | 3 | ******JAMES |
  62. | 3 | ******MARTIN |
  63. | 3 | ******MILLER |
  64. | 3 | ******SCOTT |
  65. | 3 | ******TURNER |
  66. | 3 | ******WARD |
  67. | 4 | ********ADAMS |
  68. | 4 | ********SMITH |
  69. +------+---------------+
  70. 14 rows in set (0.00 sec)

转载地址:https://www.modb.pro/db/25773

发表评论

表情:
评论列表 (有 0 条评论,308人围观)

还没有评论,来说两句吧...

相关阅读

    相关 with语句

    一 语法 with语句被用于在访问一个对象的属性或方法时避免重复使用指定对象引用。 语法: with(object) \{ stataments \} objec