今天因为一个比较头疼的mysql查询问题, 去Stack Overflow提问, 然后底下有人答复说既然用了mysql8, 不要用子查询, 直接用CTE查询. CTE查询是啥, 我直接百度了下, 然后发现, 这玩意太好用了, 但是说实话, 我可以肯定大多数人基本都不会去了解这些新出的功能,毕竟经手的项目大多数几年前的项目了,版本低. 但是说不定也有和我一样正在用mysql8版本的朋友, 所以分享出来
-
1、MySQL8.0之前,进行复杂查询时需要使用子查询来实现,SQL语句不仅语句复杂性能低,而且不够清晰。CTE的出现简化了复杂查询语句的编写,提高了SQL性能。
-
2、与子查询或者派生查询相比,CTE可以重用上次的查询结果即查询一次即可,同时,CTE可以相互引用
语法
递归查询语法
WITH RECURSIVE 别名 AS (初始化语句 -- anchor memberUNION ALL后续递归语句 -- 引用CTE名称的递归成员
SELECT * FROM 别名;
或普通的
WITH RECURSIVE 别名 AS (查询语句 -- anchor member
)
SELECT * FROM 别名;
使用
首先看看两种情况的使用
普通
普通情况下, 不要加RECURSIVE
关键字,
比如我们有个查询, A JOIN B
且条件a, 然后A JOIN C
且条件b, 最后union all:
select *
from A join B on A.id = B.aid
union all
select *
from A join C on A.id = C.aid
那我们可以这样写,CTE可以复用的方法
with a as (select * from A),b as (select * from a join B on a.id = B.aid),c as (select * from a join C on a.id = C.aid)
select * from b union all select * from c;
可以看到我们的A不需要查2次了
递归循环
这种方式可以用for循环来理解
for(int i=1,i<5;i++){
}
WITH RECURSIVE 别名 AS (初始化语句 -- anchor memberUNION ALL后续递归语句 -- 引用CTE名称的递归成员
SELECT * FROM 别名;
- 初始化语句, 也就是i=1
- 后续递归语句, 相当于i<5和i++
举个栗子:
WITH RECURSIVE cte_count (n)
AS (SELECT 1UNION ALLSELECT n + 1 FROM cte_count WHERE n < 3)
SELECT n
FROM cte_count;
这个就表示
- 先生成一个1, 放到cte_count表
- 在此基础上, 循环执行
SELECT n + 1 FROM cte_count
放入表里, 同时n<3
表示结束条件 - 最后查询展示
+---+
| n |
+---+
| 1 |
| 2 |
| 3 |
+---+
3 rows in set (0.01 sec)
大概就是这么个东西
以上都是基础的使用, 熟悉了以后可以组合, 感觉完全可以替代原来的子查询