MySQL?with語句講解
備注:測試數(shù)據(jù)庫版本為MySQL 8.0
今天我們來聊聊MySQL的with語句
對于邏輯復(fù)雜的sql,with可以大大減少臨時(shí)表的數(shù)量,提升代碼的可讀性、可維護(hù)性
MySQL 8.0終于開始支持with語句了,對于復(fù)雜查詢,可以不用寫那么多的臨時(shí)表了。
如需要scott用戶下建表及錄入數(shù)據(jù)語句,可參考:
scott建表及錄入數(shù)據(jù)sql腳本
語句結(jié)構(gòu):
with subquery_name1 as (subquery_body1),
subquery_name2 as (subquery_body2)
...
select * from subquery_name1 a, subquery_name2 b
where a.col = b.col
...優(yōu)勢
- – 代碼模塊化
- – 代碼可讀性增強(qiáng)
- – 相同查詢唯一化
一.提升代碼的可讀性和可維護(hù)性
需求:求每個部門的平均工資,以及剔除薪資低于1000的實(shí)習(xí)人員之后的平均工資
-- 求每個部門的平均工資,以及剔除薪資低于1000的實(shí)習(xí)人員之后的平均工資
-- 主查詢的from后面跟了2個臨時(shí)表,程序可讀性不佳
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的實(shí)習(xí)人員之后的平均工資
-- 2個臨時(shí)表的定時(shí)語句通過with封裝成子查詢了,程序可讀性增強(qiáng)
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的實(shí)習(xí)人員之后的平均工資
mysql> -- 主查詢的from后面跟了2個臨時(shí)表,程序可讀性不佳
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的實(shí)習(xí)人員之后的平均工資
mysql> -- 2個臨時(shí)表的定時(shí)語句通過with封裝成子查詢了,程序可讀性增強(qiáng)
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遞歸構(gòu)造數(shù)列
-- 用with遞歸構(gòu)造1-10的數(shù)據(jù) with RECURSIVE c(n) as (select 1 union all select n + 1 from c where n < 10) select n from c;
-- 用with遞歸構(gòu)造1-10的數(shù)據(jù)
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遞歸構(gòu)造級聯(lián)關(guān)系
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)到此這篇關(guān)于MySQL with語句小結(jié)的文章就介紹到這了,更多相關(guān)mysql with語句內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mysql優(yōu)化系列 DELETE子查詢改寫優(yōu)化
有個采用子查詢的DELETE執(zhí)行得非常慢,改寫成SELECT后執(zhí)行卻很快,最后把這個子查詢DELETE改寫成JOIN優(yōu)化過程2016-08-08
mysql設(shè)置指定ip遠(yuǎn)程訪問連接實(shí)例
這篇文章主要介紹了mysql設(shè)置指定ip遠(yuǎn)程訪問連接的方法,分別實(shí)例講述了從任意主機(jī)和指定ip訪問遠(yuǎn)程MySQL數(shù)據(jù)庫的方法,代碼簡單功能實(shí)用,需要的朋友可以參考下2014-10-10
MySQL 客戶端不輸入用戶名和密碼直接連接數(shù)據(jù)庫的2個方法
MySQL 客戶端不輸入用戶名和密碼直接連接數(shù)據(jù)庫的2個方法,大家可以測試下。2009-07-07
MySQL UPDATE 語句的非標(biāo)準(zhǔn)實(shí)現(xiàn)代碼
這篇文章主要介紹了MySQL UPDATE 語句的非標(biāo)準(zhǔn)實(shí)現(xiàn)代碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04

