MySQL 8.0新特性--CTE(一)
发表于:2024-10-17 作者:千家信息网编辑
千家信息网最后更新 2024年10月17日,1、CTE简介MySQL从8.0开始支持CTE,慢慢地向Oracle学习,CTE确实是个很好用的东西,特别是针对OLAP类型的SQL,可以大大简化,优化SQL.那么什么是CTE呢?个人理解:CTE(c
千家信息网最后更新 2024年10月17日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安全错误
数据库的锁怎样保障安全
怀旧服服务器可以直接买么
java游戏服务器开发
岁学软件开发晚不晚
数据库技术03139真题
江苏腾轩网络技术有限公司
黑哥网络安全之前是干什么的
信息网络技术要学什么
制作网络安全海报活动简报
越秀区质量网络技术开发价格多少
社会力量参与救灾数据库
端游原神怎么查看服务器
九星天辰诀在服务器安装教程
网鱼杀毒服务器管理
软件开发项目管理培训记录
青岛大型互联网科技公司
软件开发用的原型是什么
软件开发哪一阶段需要流程图
局域网内2台电脑都加了域服务器
海曙直销软件开发
网络安全干部职工要求
中学生网络安全班会
软件开发人力外包属于劳务费
正宗笔画输入法软件开发商
著名软件开发者被抓
软件开发定制工作室需要什么
服务器磁盘备份
服务器系统安全与维护 论文
xcode 服务器
数据库取证基础
给软件开发公司设计一个激励方案