mysql 8.0 新增了窗口函数,与Oracle一样的

MySQL从8.0开始支持窗口函数,这个功能在大多商业数据库和部分开源数据库中早已支持,有的也叫分析函数。

什么叫窗口?

窗口的概念非常重要,它可以理解为记录集合,窗口函数也就是在满足某种条件的记录集合上执行的特殊函数。对于每条记录都要在此窗口内执行函数,有的函数随着记录不同,窗口大小都是固定的,这种属于静态窗口;有的函数则相反,不同的记录对应着不同的窗口,这种动态变化的窗口叫滑动窗口。

窗口函数和普通聚合函数也很容易混淆,二者区别如下:

  • 聚合函数是将多条记录聚合为一条;而窗口函数是每条记录都会执行,有几条记录执行完还是几条。

  • 聚合函数也可以用于窗口函数中,这个后面会举例说明。

下面是一个窗口函数的简单例子:

select row_number() over(partition by user_no order by amount desc)
as rown_num,order_id,user_no,amount,create_date from order_tab

例子中,row_number()over(partition by user_no order by amount desc)这部分都属于窗口函数,它的功能是显示每个用户按照订单金额从大到小排序的序号。

按照功能划分,可以把MySQL支持的窗口函数分为如下几类:

序号函数:row_number() / rank() / dense_rank() ;分布函数:percent_rank() / cume_dist();

前后函数:lag() / lead(); 头尾函数:first_val() / last_val(); 其他函数:nth_value() / nfile()

窗口函数的基本用法如下:  函数名([expr]) over子句

其中,over是关键字,用来指定函数执行的窗口范围,如果后面括号中什么都不写,则意味着窗口包含满足where条件的所有行,窗口函数基于所有行进行计算;如果不为空,则支持以下四种语法来设置窗口:

window_name:给窗口指定一个别名,如果SQL中涉及的窗口较多,采用别名可以看起来更清晰易读。上面例子中如果指定一个别名w,则改写如下:

select * from

(   select row_number()over w as row_num,

order_id,user_no,amount,create_date

from order_tab

WINDOW w AS (partition by user_no order by amount desc)    )  t ;

  • partition子句:窗口按照那些字段进行分组,窗口函数在不同的分组上分别执行。上面的例子就按照用户id进行了分组。在每个用户id上,按照order by的顺序分别生成从1开始的顺序编号。

  • order by子句:按照哪些字段进行排序,窗口函数将按照排序后的记录顺序进行编号。可以和partition子句配合使用,也可以单独使用。上例中二者同时使用,如果没有partition子句,则会按照所有用户的订单金额排序来生成序号。

  • frame子句:frame是当前分区的一个子集,子句用来定义子集的规则,通常用来作为滑动窗口使用。比如要根据每个订单动态计算包括本订单和按时间顺序前后两个订单的平均订单金额,则可以设置如下frame子句来创建滑动窗口:

select sc.*,avg(score) over w as avg_score from sc
window w as (partition by cno order by score rows between 1 preceding
and 1 following);

得到

对于滑动窗口的范围指定,有两种方式,基于行和基于范围,具体区别如下:

(1)基于行:通常使用BETWEEN frame_start AND frame_end语法来表示行范围,frame_start和frame_end可以支持如下关键字,来确定不同的动态行记录:

CURRENT ROW 边界是当前行,一般和其他范围关键字一起使用

UNBOUNDED PRECEDING 边界是分区中的第一行

UNBOUNDED FOLLOWING 边界是分区中的最后一行

expr PRECEDING  边界是当前行减去expr的值

expr FOLLOWING  边界是当前行加上expr的值

下面都是合法的范围:

rows BETWEEN 1 PRECEDING AND 1 FOLLOWING 窗口范围是当前行、前一行、后一行一共三行记录。

rows  UNBOUNDED FOLLOWING 窗口范围是当前行到分区中的最后一行。

rows BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING 窗口范围是当前分区中所有行,等同于不写。

(2)基于范围:和基于行类似,但有些范围不是直接可以用行数来表示的,比如希望窗口范围是一周前的订单开始,截止到当前行,则无法使用rows来直接表示,此时就可以使用范围来表示窗口:INTERVAL 7 DAY PRECEDING。Linux中常见的最近1分钟、5分钟负载是一个典型的应用场景。

有的函数不管有没有frame子句,它的窗口都是固定的,也就是前面介绍的静态窗口,这些函数包括如下:

  • CUME_DIST()

  • DENSE_RANK()

  • LAG()

  • LEAD()

  • NTILE()

  • PERCENT_RANK()

  • RANK()

  • ROW_NUMBER()

接下来我们以上例的订单表为例,来介绍每个函数的使用方法。表中各字段含义按顺序分别为订单号、用户id、订单金额、订单创建日期。

序号函数不再介绍了。 row_number() / rank() / dense_rank()。

分布函数  percent_rank()/cume_dist()。

percent_rank()

  • 用途:和之前的RANK()函数相关,每行按照如下公式进行计算:

    (rank - 1) / (rows - 1)

    其中,rank为RANK()函数产生的序号,rows为当前窗口的记录总行数。

  • 应用场景:没想出来……感觉不太常用,看个例子吧

percent列按照公式(rank - 1) / (rows - 1)带入rank值(row_num列)和rows值(user_no为‘001’和‘002’的值均为5)。

cume_dist()

用途:分组内小于等于当前rank值的行数/分组内总行数,这个函数比percen_rank使用场景更多。

应用场景:大于等于当前订单金额的订单比例有多少。

列cume显示了预期的数据分布结果。

六、前后函数

lead(n)/lag(n)。

用途:分区中位于当前行前n行(lead)/后n行(lag)的记录值。使用场景:查询上一个订单距离当前订单的时间间隔。

select order_id,user_no,amount,create_date,last_date,
date_diff(create_date,last_date) as diff from
(
select order_id,user_no,amount,create_date,lag(create_date,1) over w
as list_date
from order_tab window w as (partition by user_no order by create_date)
) t;

得到

内层SQL先通过lag函数得到上一次订单的日期,外层SQL再将本次订单和上次订单日期做差得到时间间隔diff。

七、头尾函数

头尾函数——first_val(expr)/last_val(expr)。

用途:得到分区中的第一个/最后一个指定参数的值。使用场景:查询截止到当前订单,按照日期排序第一个订单和最后一个订单的订单金额。

结果和预期一致,比如order_id为4的记录,first_amount和last_amount分别记录了用户‘001’截止到时间2018-01-03 00:00:00为止,第一条订单金额100和最后一条订单金额800,注意这里是按时间排序的最早订单和最晚订单,并不是最小金额和最大金额订单。

八、其他函数

其他函数——nth_value(expr,n)/nfile(n)。

nth_value(expr,n)

  • 用途:返回窗口中第N个expr的值,expr可以是表达式,也可以是列名。

  • 应用场景:每个用户订单中显示本用户金额排名第二和第三的订单金额。

nfile(n)

  • 用途:将分区中的有序数据分为n个桶,记录桶号。

  • 应用场景:将每个用户的订单按照订单金额分成3组。

SQL如下:

此函数在数据分析中应用较多,比如由于数据量大,需要将数据平均分配到N个并行的进程分别计算,此时就可以用NFILE(N)对数据进行分组,由于记录数不一定被N整除,所以数据不一定完全平均,然后将不同桶号的数据再分配。

九、聚合函数作为窗口函数

  • 用途:在窗口中每条记录动态应用聚合函数(sum/avg/max/min/count),可以动态计算在指定的窗口内的各种聚合函数值。

  • 应用场景:每个用户按照订单id,截止到当前的累计订单金额/平均订单金额/最大订单金额/最小订单金额/订单数是多少?

SQL如下:

select order_id,user_no,amount,create_date,sum(amount)
over w as sum1
from order_tab window w as (partition by user_no order by order_id)

除了这几个常用的聚合函数,还有一些也可以使用,比如BIT_AND()、STD()等等,具体查看官方文档。

chapter8 备份与恢复

1. mysqldump 命令

mysqldump把数据库中的数据备份为一个文本文件,表结构与表的数据将存储在生成的文本文件中。

mysqldump 的原理很简单:先查出表结构,再在文本中生成一条create 语句。然后把表中的记录转化为insert 语句。还原数据的时候就是用 create 与insert 来还原表。

mysqldump可以备份一个、多个、所有数据库。

语法:mysqldump -u用户名 -p密码 数据库名 >dump文件的路径和名称

mysqldump -u username -p dbname table1 table2... >backupname.sql

一般备份为sql格式的,也可以是sql格式的。

myqldump不是sql语句,mysqldump是mysql用于转存储数据库的实用程序。

不能在MySQL可视化工具或者DOS里的mysql下直接执行。

其实应该直接在cmd+r打开的窗口直接执行。

备份多个数据库

mysqldump -u username -p --databases dbname1 dbname2... >backupname.sql

备份所有数据库

mysqldump -u username -p --all --databases >backupname.sql

2. 直接复制整个数据库

此时最好停止服务器,保证复制期间没有数据变化。

3.mysqlhotcopy 工具, 这不是mysql自带的,主要安装perl的数据接口包。

4.数据还原 mysql

mysql -u root -p (dbname 可写可不写) <backup.sql

mysql -u root -p <D:\all.sql  恢复所有数据库

5.表的导入导出

导出文本文件

select ... into outfile

select sno from student into outfile'D:\sno.txt' [option]

option有以下几种

fields terminated by '字符串' , 字段的分隔符,默认是\t

fields enclosed by '字符串',

fields terminated by '字符串'

lines starting by '' , 每行开头的字符 ,默认没有

lines terminated by''  每行的结束符,默认是\n

SELECT sno,sname FROM student INTO OUTFILE 'D:\info.txt' FIELDS TERMINATED BY '\、' 
LINES STARTING BY '\>' TERMINATED BY '\r\n'

导入文本文件

load data infile '文件路径' into table student

fields terminated by'\t' lines terminated by'\r\n' ignore 1 lines

create table student2 like student;
SELECT * FROM student INTO OUTFILE 'D:\info2.txt' FIELDS TERMINATED BY '\、' LINES STARTING BY '\>' TERMINATED BY '\r\n'; load data infile 'D:\info2.txt' into table student2 FIELDS TERMINATED BY '\、' LINES STARTING BY '\>' TERMINATED BY '\r\n'

能不能导入数据到表的某些字段中?而不是全部。

chapter9 mysql优化查询

1.分析查询语句 explain 或者desc select 语句;

explain select * from student;

rows表示返回查询结果所检验的行数。

可以去看看用了索引查询速度的变化。上述如果对 sdept 建立了索引

发现rows变成了5。

并不是说加了索引查询都会提高。

(1) where name like '%好', 开头就是%, 即使name 加了索引也没用;

(2)用了or  两个条件必须同为索引,否则不会使用索引进行查询。

2. 优化数据库结构

如果一个字段很多但是使用频率低,那么可以把它分解为多个表。

如果两张表的部分字段用的很多,可以建立一张中间表,以后都在中间表里进行查询,不用去关联这两张原表了。

3. 优化插入记录的速度。

插入记录时,索引、唯一性校验都会影响插入记录的速度。一次插入多条数据和多次插入记录的速度都不同。

(1)禁用索引  alter table 表名 disable keys;

重启索引 alter table 表名 enable keys;

(2)禁用唯一性检查。

mysql会检查插入的记录。

禁用唯一性 set unique_checks=0;   启用唯一性  set unique_checks=1;

4. 优化insert 语句

insert into student values('001','CC', ‘02’,'PC'),('002','CD', ‘02’,'PC') 这种比单独的一条条insert 更快。

最好用load data infile 速度较快。

MySQL(2): 窗口函数\备份与恢复\性能优化\权限管理的更多相关文章

  1. 我的MYSQL学习心得(十三) 权限管理

    我的MYSQL学习心得(十三) 权限管理 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) ...

  2. SQL Server性能优化与管理的艺术 附件下载地址

    首先感谢读者们对鄙人的支持,购买了<SQL Server性能优化与管理的艺术>,由于之前出版社的一些疏忽,附件没有上传成功,再次本人深表歉意. 请需要下载附件的读者从下面链接下载,谢谢: ...

  3. MySQL/MariaDB数据库的用户和权限管理

    MySQL/MariaDB数据库的用户和权限管理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.元数据数据库(mysql) 系统授权表(均在mysql数据库中): db hos ...

  4. mysql笔记03 查询性能优化

    查询性能优化 1. 为什么查询速度会慢? 1). 如果把查询看作是一个任务,那么它由一系列子任务组成,每个子任务都会消耗一定的时间.如果要优化查询,实际上要优化其子任务,要么消除其中一些子任务,要么减 ...

  5. MySql学习(七) —— 查询性能优化 深入理解MySql如何执行查询

    本篇深入了解查询优化和服务器的内部机制,了解MySql如何执行特定查询,从中也可以知道如何更改查询执行计划,当我们深入理解MySql如何真正地执行查询,明白高效和低效的真正含义,在实际应用中就能扬长避 ...

  6. Mysql学习笔记(十三)权限管理

    学习内容: 1.权限管理: 关于mysql的权限简单的理解就是mysql允许你做你权利以内的事情,不可以越界.比如只允许你执行select操作,那么你就不能执行update操作.只允许你从某台机器上连 ...

  7. Mysql Join语法以及性能优化

    引言 内外联结的区别是内联结将去除所有不符合条件的记录,而外联结则保留其中部分.外左联结与外右联结的区别在于如果用A左联结B则A中所有记录都会保留在结果中,此时B中只有符合联结条件的记录,而右联结相反 ...

  8. 【MySQL】多表查询&事务&权限管理

    多表查询: 查询语法: select 列名列表 from 表名列表 where.... 例子: 创建部门表 CREATE TABLE dept( id INT PRIMARY KEY AUTO_INC ...

  9. MySQL分页查询的性能优化

    MySQL limit分页查询的性能优化 Mysql的分页查询十分简单,但是当数据量大的时候一般的分页就吃不消了. 传统分页查询:SELECT c1,c2,cn… FROM table LIMIT n ...

  10. mysql问题排查与性能优化

     MySQL 问题排查都有哪些手段? 使用 show processlist 命令查看当前所有连接信息. 使用 explain 命令查询 SQL 语句执行计划. 开启慢查询日志,查看慢查询的 SQL. ...

随机推荐

  1. python3.10调用邮件SMTP报错: ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:997)解决

    一: python3.10调用邮件SMTP报错: ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake fa ...

  2. vue基础之keep-alvie保持历史页面数据不变,切换页面后数据不变keep-alvie

    1:路由配置文件设置 { path: '/MenuM', component: Layout, redirect: '/MenuM', children: [ { path: 'MenuM', nam ...

  3. 微信公众号签名错误(invalid signature)的问题排查

    之前写好的代码,好多项目一直在用没啥问题,今天做新项目,在调用的时候,wx.config提示签名错误(invalid signature),这搞得相当郁闷,没办法,只能重新一点一点调试. 按照官方的说 ...

  4. 编程哲学之 C# 篇:005——"Hello,World!"

    如第一章说明,程序员的创造能力最接近于神,那么从现在开始,让我们来开始愉快地创造世界吧! 用解决方案来管理我们的创作 运行我们安装好的Visual Studio(以后一般情况下都会简称为VS),如下图 ...

  5. 基于 Ubuntu 服务器配置原生的 Socks5 网关代理服务器

    常见的代理协议有 http.https.socks4/5 这三种,http协议的代理搭建方案最简单,但是http代理无法访问https网站,https代理无法实现调用远端dns,所以我个人推荐使用Sc ...

  6. 接水问题(NOIP 2010 PJT2)

    这个的思路就是让各个水龙头所用的时间尽可能地接近,可以先向优先队列中推入前m个数,由于开的是小根堆最小的数在前面我们把它拿出来,加上下一个人所需的时间.如此反复,直到都接完水,最大值就是答案. #in ...

  7. 2021级《JAVA语言程序设计》上机考试试题6

    首先管理员页面 代码: <%@ page language="java" contentType="text/html; charset=UTF-8" p ...

  8. 【Oculus Interaction SDK】(十二)Meta Quest 如何开启透视(Passthrough)

    前言 前段时间 Oculus 的 SDK 频繁更新,很多已有的教程都不再适用于现在的版本了.本系列文章的主要目的是记录现版本常见功能的实现方法,便于自己后续开发.当然,不排除我文章刚写完 SDK 又变 ...

  9. vue data为什么是函数

    vue data是函数的原因: 1.防止data复用: 2.data独立性: 3.作用域: 4.js的特性. 总结来说,如果data是一个函数的话,这样每复用一次组件,就会返回一份新的data(类似于 ...

  10. Vue3 ref 模板引用获取不到节点

    ref模板引用必须要在组件实例挂载完成之后才可以访问.如果你是在组合式 API 里面写的组件,那么 setup 函数比任何周期函数都早,所以不可能在该函数中执行时获取得到ref--组件实例. 官网关于 ...