MySQL 8.0新特性--CTE(一)
发表于:2025-02-01 作者:千家信息网编辑
千家信息网最后更新 2025年02月01日,1、CTE简介MySQL从8.0开始支持CTE,慢慢地向Oracle学习,CTE确实是个很好用的东西,特别是针对OLAP类型的SQL,可以大大简化,优化SQL.那么什么是CTE呢?个人理解:CTE(c
千家信息网最后更新 2025年02月01日MySQL 8.0新特性--CTE(一)
1、CTE简介
MySQL从8.0开始支持CTE,慢慢地向Oracle学习,CTE确实是个很好用的东西,特别是针对OLAP类型的SQL,可以大大简化,优化SQL.
那么什么是CTE呢?
个人理解:CTE(common table expression)是一个临时的结果集,类似一个函数,一旦定义好,可以多次调用。
2、CTE语法
with_clause: WITH [RECURSIVE] cte_name [(col_name [, col_name] ...)] AS (subquery) [, cte_name [(col_name [, col_name] ...)] AS (subquery)] ...
(1)列别名可以在不同的位置定义
mysql> WITH cte (col1, col2) AS -> ( -> SELECT 1, 2 -> UNION ALL -> SELECT 3, 4 -> ) -> SELECT col1, col2 FROM cte;+------+------+| col1 | col2 |+------+------+| 1 | 2 || 3 | 4 |+------+------+2 rows in set (0.00 sec)等价与:mysql> WITH cte AS -> ( -> SELECT 1 AS col1, 2 AS col2 -> UNION ALL -> SELECT 3, 4 -> ) -> SELECT col1, col2 FROM cte;+------+------+| col1 | col2 |+------+------+| 1 | 2 || 3 | 4 |+------+------+2 rows in set (0.00 sec)
(2) CTE用在Select操作
mysql> create table t1(a int,b int);mysql> insert into t1 values(1,1),(2,2),(3,3);mysql> with t as (select a+2 c,b from t1) select c,b from t;+------+------+| c | b |+------+------+| 3 | 1 || 4 | 2 || 5 | 3 |+------+------+3 rows in set (0.00 sec)
(3)CTE用在DML操作
mysql> with t as (select a+2 as a,b from t1) update t1,t set t1.a=t.a+10 where t1.a=t.a;mysql> select * from t1;+------+------+| a | b |+------+------+| 1 | 1 || 2 | 2 || 13 | 3 |+------+------+3 rows in set (0.00 sec)mysql> with t as (select a+2 as a,b from t1) delete t1 from t1,t where t1.a=t.a;mysql> select * from t1;+------+------+| a | b |+------+------+| 1 | 1 || 2 | 2 |+------+------+2 rows in set (0.00 sec)mysql> insert into t1 with t as (select 10*a as a,b from t1) select * from t;mysql> select * from t1;+------+------+| a | b |+------+------+| 1 | 1 || 2 | 2 || 3 | 3 || 10 | 1 || 20 | 2 || 30 | 3 |+------+------+6 rows in set (0.00 sec)
3、CTE可以优化SQL
(1)下面第一条SQL可以改写成如下两种CTE简化形式
mysql> select count(*) from employees e1 left join (select * from employees) e2 on e1.emp_no=e2.emp_no left join (select * from employees) e3 on e2.emp_no=e3.emp_no; mysql> with e2 as (select * from employees), e3 as (select * from employees) select count(*) from employees e1 left join e2 on e1.emp_no=e2.emp_no left join e3 on e2.emp_no=e3.emp_no; mysql> with e as(select * from employees) select count(*) from employees e1 left join e e2 on e1.emp_no=e2.emp_no left join e e3 on e2.emp_no=e3.emp_no;
(2)CTE的本质是子查询,所以子查询的一些特性都适用,如子查询合并。
mysql> desc with e as(select /*+ set_var(optimizer_switch='derived_merge=off')*/ * from employees) -> select count(*) from employees e1 -> left join e e2 on e1.emp_no=e2.emp_no -> left join e e3 on e2.emp_no=e3.emp_no;+----+-------------+------------+------------+-------+---------------+-------------+---------+------------------+--------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+------------+------------+-------+---------------+-------------+---------+------------------+--------+----------+-------------+| 1 | PRIMARY | e1 | NULL | index | NULL | PRIMARY | 4 | NULL | 299512 | 100.00 | Using index || 1 | PRIMARY || NULL | ref | | | 4 | testdb.e1.emp_no | 10 | 100.00 | NULL || 1 | PRIMARY | | NULL | ref | | | 4 | e2.emp_no | 10 | 100.00 | NULL || 2 | DERIVED | employees | NULL | ALL | NULL | NULL | NULL | NULL | 299512 | 100.00 | NULL |+----+-------------+------------+------------+-------+---------------+-------------+---------+------------------+--------+----------+-------------+4 rows in set, 2 warnings (0.00 sec)
(3)CTE可以起到减少插入临时表数据,优化SQL的作用
mysql> flush status;Query OK, 0 rows affected (0.02 sec)mysql> select /*+ set_var(optimizer_switch='derived_merge=off')*/ * from -> (select * from t_group) t1 -> join (select * from t_group) t2 -> on t1.emp_no=t2.emp_no;+--------+---------+------------+------------+--------+---------+------------+------------+| emp_no | dept_no | from_date | to_date | emp_no | dept_no | from_date | to_date |+--------+---------+------------+------------+--------+---------+------------+------------+| 22744 | d006 | 1986-12-01 | 9999-01-01 | 22744 | d006 | 1986-12-01 | 9999-01-01 || 24007 | d005 | 1986-12-01 | 9999-01-01 | 24007 | d005 | 1986-12-01 | 9999-01-01 || 30970 | d005 | 1986-12-01 | 2017-03-29 | 30970 | d005 | 1986-12-01 | 2017-03-29 || 31112 | d002 | 1986-12-01 | 1993-12-10 | 31112 | d002 | 1986-12-01 | 1993-12-10 || 40983 | d005 | 1986-12-01 | 9999-01-01 | 40983 | d005 | 1986-12-01 | 9999-01-01 || 46554 | d008 | 1986-12-01 | 1992-05-27 | 46554 | d008 | 1986-12-01 | 1992-05-27 || 48317 | d008 | 1986-12-01 | 1989-01-11 | 48317 | d008 | 1986-12-01 | 1989-01-11 || 49667 | d007 | 1986-12-01 | 9999-01-01 | 49667 | d007 | 1986-12-01 | 9999-01-01 || 50449 | d005 | 1986-12-01 | 9999-01-01 | 50449 | d005 | 1986-12-01 | 9999-01-01 || 10004 | d004 | 1986-12-01 | 9999-01-01 | 10004 | d004 | 1986-12-01 | 9999-01-01 |+--------+---------+------------+------------+--------+---------+------------+------------+10 rows in set (0.00 sec)mysql> show status like '%handler_write%';+---------------+-------+| Variable_name | Value |+---------------+-------+| Handler_write | 20 |+---------------+-------+1 row in set (0.00 sec)mysql> flush status;Query OK, 0 rows affected (0.02 sec)mysql> with t as(select /*+ set_var(optimizer_switch='derived_merge=off')*/ * from t_group) -> select * from t t1 -> join t t2 on t1.emp_no=t2.emp_no;+--------+---------+------------+------------+--------+---------+------------+------------+| emp_no | dept_no | from_date | to_date | emp_no | dept_no | from_date | to_date |+--------+---------+------------+------------+--------+---------+------------+------------+| 22744 | d006 | 1986-12-01 | 9999-01-01 | 22744 | d006 | 1986-12-01 | 9999-01-01 || 24007 | d005 | 1986-12-01 | 9999-01-01 | 24007 | d005 | 1986-12-01 | 9999-01-01 || 30970 | d005 | 1986-12-01 | 2017-03-29 | 30970 | d005 | 1986-12-01 | 2017-03-29 || 31112 | d002 | 1986-12-01 | 1993-12-10 | 31112 | d002 | 1986-12-01 | 1993-12-10 || 40983 | d005 | 1986-12-01 | 9999-01-01 | 40983 | d005 | 1986-12-01 | 9999-01-01 || 46554 | d008 | 1986-12-01 | 1992-05-27 | 46554 | d008 | 1986-12-01 | 1992-05-27 || 48317 | d008 | 1986-12-01 | 1989-01-11 | 48317 | d008 | 1986-12-01 | 1989-01-11 || 49667 | d007 | 1986-12-01 | 9999-01-01 | 49667 | d007 | 1986-12-01 | 9999-01-01 || 50449 | d005 | 1986-12-01 | 9999-01-01 | 50449 | d005 | 1986-12-01 | 9999-01-01 || 10004 | d004 | 1986-12-01 | 9999-01-01 | 10004 | d004 | 1986-12-01 | 9999-01-01 |+--------+---------+------------+------------+--------+---------+------------+------------+10 rows in set, 1 warning (0.00 sec)mysql> show status like '%handler_write%';+---------------+-------+| Variable_name | Value |+---------------+-------+| Handler_write | 10 |+---------------+-------+1 row in set (0.00 sec)
CTE除了一般功能外,还可以实现递归一些复杂SQL需求,参考MySQL 8.0新特性--CTE(二)
参考链接
13.2.13 WITH Syntax (Common Table Expressions)
查询
特性
参考
不同
复杂
东西
个人
位置
作用
函数
别名
功能
形式
数据
本质
等价
简介
类型
结果
语法
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
徐州互联网软件开发诚信服务
福建运营软件开发销售价格
rb服务器
网络安全多少不准
大数据网络技术专业学什么
h3c服务器镜像安装
网络安全法我来普法
服务器容灾方案
系统网络安全模式
非法吸收公众存款软件开发
数据库技术的基础知识ppt
数字化副本移交接收软件开发
联想服务器 客服电话
高校网络安全教育班会
中国软件开发中心待遇
数据库系统及其应用
广西刺猬网络技术有限公司
上海精英网络技术开发口碑推荐
4月29首都网络安全日
网络技术课本百度云
有关软件开发的书籍
数据库课程亮点
rb服务器
崇明区企业软件开发诚信服务
网络安全职业测试
处对象有什么软件开发
网络安全渗透工程师培训通知
ip网络安全教育
东吴掌财服务器异常
sun服务器系统