mysql窗口函数_MySQL8.0窗口函数入门实践及总结

前言

MySQL8.0之前,做数据排名统计等相当痛苦,因为没有像Oracle、SQL SERVER 、PostgreSQL等其他数据库那样的窗口函数。但随着MySQL8.0中新增了窗口函数之后,针对这类统计就再也不是事了,本文就以常用的排序实例介绍MySQL的窗口函数。

1、准备工作

创建表及测试数据

mysql> use testdb;

Database changed

/* 创建表 */

mysql> create table tb_score(id int primary key auto_increment,stu_no varchar(10),course varchar(50),score decimal(4,1),key idx_stuNo_course(stu_no,course));

Query OK, 0 rows affected (0.03 sec)

mysql> show tables;

+------------------+

| Tables_in_testdb |

+------------------+

| tb_score |

+------------------+

/* 新增一批测试数据 */

mysql> insert into tb_score(stu_no,course,score)values('2020001','mysql',90),('2020001','C++',85),('2020003','English',100),('2020002','mysql',50),('2020002','C++',70),('2020002','English',99);

Query OK, 6 rows affected (0.00 sec)

Records: 6 Duplicates: 0 Warnings: 0

mysql> insert into tb_score(stu_no,course,score)values('2020003','mysql',78),('2020003','C++',81),('2020003','English',80),('2020004','mysql',80),('2020004','C++',60),('2020004','English',100);

Query OK, 6 rows affected (0.01 sec)

Records: 6 Duplicates: 0 Warnings: 0

mysql> insert into tb_score(stu_no,course,score)values('2020005','mysql',98),('2020005','C++',96),('2020005','English',70),('2020006','mysql',60),('2020006','C++',90),('2020006','English',70);

Query OK, 6 rows affected (0.01 sec)

Records: 6 Duplicates: 0 Warnings: 0

mysql> insert into tb_score(stu_no,course,score)values('2020007','mysql',50),('2020007','C++',66),('2020007','English',76),('2020008','mysql',90),('2020008','C++',69),('2020008','English',86);

Query OK, 6 rows affected (0.01 sec)

Records: 6 Duplicates: 0 Warnings: 0

mysql> insert into tb_score(stu_no,course,score)values('2020009','mysql',70),('2020009','C++',66),('2020009','English',86),('2020010','mysql',75),('2020010','C++',76),('2020010','English',81);

Query OK, 6 rows affected (0.01 sec)

Records: 6 Duplicates: 0 Warnings: 0

mysql> insert into tb_score(stu_no,course,score)values('2020011','mysql',90),('2020012','C++',85),('2020011','English',84),('2020012','English',75),('2020013','C++',96),('2020013','English',88);

Query OK, 6 rows affected (0.01 sec)

Records: 6 Duplicates: 0 Warnings: 0

2、统计每门课程分数的排名

根据每门课程的分数从高到低进行排名,此时,会出现分数相同时怎么处理的问题,下面就根据不同的窗口函数来处理不同场景的需求

ROW_NUMBER

由结果可以看出,分数相同时按照学号顺序进行排名

mysql> select stu_no,course,score, row_number()over(partition by course order by score desc ) rn

-> from tb_score;

+---------+---------+-------+----+

| stu_no | course | score | rn |

+---------+---------+-------+----+

| 2020005 | C++ | 96.0 | 1 |

| 2020013 | C++ | 96.0 | 2 |

| 2020006 | C++ | 90.0 | 3 |

| 2020001 | C++ | 85.0 | 4 |

| 2020012 | C++ | 85.0 | 5 |

| 2020003 | C++ | 81.0 | 6 |

| 2020010 | C++ | 76.0 | 7 |

| 2020002 | C++ | 70.0 | 8 |

| 2020008 | C++ | 69.0 | 9 |

| 2020007 | C++ | 66.0 | 10 |

| 2020009 | C++ | 66.0 | 11 |

| 2020004 | C++ | 60.0 | 12 |

| 2020003 | English | 100.0 | 1 |

| 2020004 | English | 100.0 | 2 |

| 2020002 | English | 99.0 | 3 |

| 2020013 | English | 88.0 | 4 |

| 2020008 | English | 86.0 | 5 |

| 2020009 | English | 86.0 | 6 |

| 2020011 | English | 84.0 | 7 |

| 2020010 | English | 81.0 | 8 |

| 2020003 | English | 80.0 | 9 |

| 2020007 | English | 76.0 | 10 |

| 2020012 | English | 75.0 | 11 |

| 2020005 | English | 70.0 | 12 |

| 2020006 | English | 70.0 | 13 |

| 2020005 | mysql | 98.0 | 1 |

| 2020001 | mysql | 90.0 | 2 |

| 2020008 | mysql | 90.0 | 3 |

| 2020011 | mysql | 90.0 | 4 |

| 2020004 | mysql | 80.0 | 5 |

| 2020003 | mysql | 78.0 | 6 |

| 2020010 | mysql | 75.0 | 7 |

| 2020009 | mysql | 70.0 | 8 |

| 2020006 | mysql | 60.0 | 9 |

| 2020002 | mysql | 50.0 | 10 |

| 2020007 | mysql | 50.0 | 11 |

+---------+---------+-------+----+

36 rows in set (0.00 sec)mysql> select stu_no,course,score, row_number()over(partition by course order by score desc ) rn

-> from tb_score;

+---------+---------+-------+----+

| stu_no | course | score | rn |

+---------+---------+-------+----+

| 2020005 | C++ | 96.0 | 1 |

| 2020013 | C++ | 96.0 | 2 |

| 2020006 | C++ | 90.0 | 3 |

| 2020001 | C++ | 85.0 | 4 |

| 2020012 | C++ | 85.0 | 5 |

| 2020003 | C++ | 81.0 | 6 |

| 2020010 | C++ | 76.0 | 7 |

| 2020002 | C++ | 70.0 | 8 |

| 2020008 | C++ | 69.0 | 9 |

| 2020007 | C++ | 66.0 | 10 |

| 2020009 | C++ | 66.0 | 11 |

| 2020004 | C++ | 60.0 | 12 |

| 2020003 | English | 100.0 | 1 |

| 2020004 | English | 100.0 | 2 |

| 2020002 | English | 99.0 | 3 |

| 2020013 | English | 88.0 | 4 |

| 2020008 | English | 86.0 | 5 |

| 2020009 | English | 86.0 | 6 |

| 2020011 | English | 84.0 | 7 |

| 2020010 | English | 81.0 | 8 |

| 2020003 | English | 80.0 | 9 |

| 2020007 | English | 76.0 | 10 |

| 2020012 | English | 75.0 | 11 |

| 2020005 | English | 70.0 | 12 |

| 2020006 | English | 70.0 | 13 |

| 2020005 | mysql | 98.0 | 1 |

| 2020001 | mysql | 90.0 | 2 |

| 2020008 | mysql | 90.0 | 3 |

| 2020011 | mysql | 90.0 | 4 |

| 2020004 | mysql | 80.0 | 5 |

| 2020003 | mysql | 78.0 | 6 |

| 2020010 | mysql | 75.0 | 7 |

| 2020009 | mysql | 70.0 | 8 |

| 2020006 | mysql | 60.0 | 9 |

| 2020002 | mysql | 50.0 | 10 |

| 2020007 | mysql | 50.0 | 11 |

+---------+---------+-------+----+

36 rows in set (0.00 sec)

DENSE_RANK

为了让分数相同时排名也相同,则可以使用DENSE_RANK函数,结果如下:

mysql> select stu_no,course,score, DENSE_RANK()over(partition by course order by score desc ) rn

-> from tb_score ;

+---------+---------+-------+----+

| stu_no | course | score | rn |

+---------+---------+-------+----+

| 2020005 | C++ | 96.0 | 1 |

| 2020013 | C++ | 96.0 | 1 |

| 2020006 | C++ | 90.0 | 2 |

| 2020001 | C++ | 85.0 | 3 |

| 2020012 | C++ | 85.0 | 3 |

| 2020003 | C++ | 81.0 | 4 |

| 2020010 | C++ | 76.0 | 5 |

| 2020002 | C++ | 70.0 | 6 |

| 2020008 | C++ | 69.0 | 7 |

| 2020007 | C++ | 66.0 | 8 |

| 2020009 | C++ | 66.0 | 8 |

| 2020004 | C++ | 60.0 | 9 |

| 2020003 | English | 100.0 | 1 |

| 2020004 | English | 100.0 | 1 |

| 2020002 | English | 99.0 | 2 |

| 2020013 | English | 88.0 | 3 |

| 2020008 | English | 86.0 | 4 |

| 2020009 | English | 86.0 | 4 |

| 2020011 | English | 84.0 | 5 |

| 2020010 | English | 81.0 | 6 |

| 2020003 | English | 80.0 | 7 |

| 2020007 | English | 76.0 | 8 |

| 2020012 | English | 75.0 | 9 |

| 2020005 | English | 70.0 | 10 |

| 2020006 | English | 70.0 | 10 |

| 2020005 | mysql | 98.0 | 1 |

| 2020001 | mysql | 90.0 | 2 |

| 2020008 | mysql | 90.0 | 2 |

| 2020011 | mysql | 90.0 | 2 |

| 2020004 | mysql | 80.0 | 3 |

| 2020003 | mysql | 78.0 | 4 |

| 2020010 | mysql | 75.0 | 5 |

| 2020009 | mysql | 70.0 | 6 |

| 2020006 | mysql | 60.0 | 7 |

| 2020002 | mysql | 50.0 | 8 |

| 2020007 | mysql | 50.0 | 8 |

+---------+---------+-------+----+

36 rows in set (0.00 sec)

RANK

DENSE_RANK的结果是分数相同时排名相同了,但是下一个名次是紧接着上一个名次的,如果2个并列的第1之后,下一个我想是第3名,则可以使用RANK函数实现

mysql> select stu_no,course,score, rank()over(partition by course order by score desc ) rn

-> from tb_score;

+---------+---------+-------+----+

| stu_no | course | score | rn |

+---------+---------+-------+----+

| 2020005 | C++ | 96.0 | 1 |

| 2020013 | C++ | 96.0 | 1 |

| 2020006 | C++ | 90.0 | 3 |

| 2020001 | C++ | 85.0 | 4 |

| 2020012 | C++ | 85.0 | 4 |

| 2020003 | C++ | 81.0 | 6 |

| 2020010 | C++ | 76.0 | 7 |

| 2020002 | C++ | 70.0 | 8 |

| 2020008 | C++ | 69.0 | 9 |

| 2020007 | C++ | 66.0 | 10 |

| 2020009 | C++ | 66.0 | 10 |

| 2020004 | C++ | 60.0 | 12 |

| 2020003 | English | 100.0 | 1 |

| 2020004 | English | 100.0 | 1 |

| 2020002 | English | 99.0 | 3 |

| 2020013 | English | 88.0 | 4 |

| 2020008 | English | 86.0 | 5 |

| 2020009 | English | 86.0 | 5 |

| 2020011 | English | 84.0 | 7 |

| 2020010 | English | 81.0 | 8 |

| 2020003 | English | 80.0 | 9 |

| 2020007 | English | 76.0 | 10 |

| 2020012 | English | 75.0 | 11 |

| 2020005 | English | 70.0 | 12 |

| 2020006 | English | 70.0 | 12 |

| 2020005 | mysql | 98.0 | 1 |

| 2020001 | mysql | 90.0 | 2 |

| 2020008 | mysql | 90.0 | 2 |

| 2020011 | mysql | 90.0 | 2 |

| 2020004 | mysql | 80.0 | 5 |

| 2020003 | mysql | 78.0 | 6 |

| 2020010 | mysql | 75.0 | 7 |

| 2020009 | mysql | 70.0 | 8 |

| 2020006 | mysql | 60.0 | 9 |

| 2020002 | mysql | 50.0 | 10 |

| 2020007 | mysql | 50.0 | 10 |

+---------+---------+-------+----+

36 rows in set (0.01 sec)

这样就实现了各种排序需求。

NTILE

NTILE函数的作用是对每个分组排名后,再将对应分组分成N个小组,例如

mysql> select stu_no,course,score, rank()over(partition by course order by score desc )rn,NTILE(2)over(partition by course order by score desc ) rn_group from tb_score;

+---------+---------+-------+----+----------+

| stu_no | course | score | rn | rn_group |

+---------+---------+-------+----+----------+

| 2020005 | C++ | 96.0 | 1 | 1 |

| 2020013 | C++ | 96.0 | 1 | 1 |

| 2020006 | C++ | 90.0 | 3 | 1 |

| 2020001 | C++ | 85.0 | 4 | 1 |

| 2020012 | C++ | 85.0 | 4 | 1 |

| 2020003 | C++ | 81.0 | 6 | 1 |

| 2020010 | C++ | 76.0 | 7 | 2 |

| 2020002 | C++ | 70.0 | 8 | 2 |

| 2020008 | C++ | 69.0 | 9 | 2 |

| 2020007 | C++ | 66.0 | 10 | 2 |

| 2020009 | C++ | 66.0 | 10 | 2 |

| 2020004 | C++ | 60.0 | 12 | 2 |

| 2020003 | English | 100.0 | 1 | 1 |

| 2020004 | English | 100.0 | 1 | 1 |

| 2020002 | English | 99.0 | 3 | 1 |

| 2020013 | English | 88.0 | 4 | 1 |

| 2020008 | English | 86.0 | 5 | 1 |

| 2020009 | English | 86.0 | 5 | 1 |

| 2020011 | English | 84.0 | 7 | 1 |

| 2020010 | English | 81.0 | 8 | 2 |

| 2020003 | English | 80.0 | 9 | 2 |

| 2020007 | English | 76.0 | 10 | 2 |

| 2020012 | English | 75.0 | 11 | 2 |

| 2020005 | English | 70.0 | 12 | 2 |

| 2020006 | English | 70.0 | 12 | 2 |

| 2020005 | mysql | 98.0 | 1 | 1 |

| 2020001 | mysql | 90.0 | 2 | 1 |

| 2020008 | mysql | 90.0 | 2 | 1 |

| 2020011 | mysql | 90.0 | 2 | 1 |

| 2020004 | mysql | 80.0 | 5 | 1 |

| 2020003 | mysql | 78.0 | 6 | 1 |

| 2020010 | mysql | 75.0 | 7 | 2 |

| 2020009 | mysql | 70.0 | 8 | 2 |

| 2020006 | mysql | 60.0 | 9 | 2 |

| 2020002 | mysql | 50.0 | 10 | 2 |

| 2020007 | mysql | 50.0 | 10 | 2 |

+---------+---------+-------+----+----------+

36 rows in set (0.01 sec)

3、窗口函数小结

MySQL中还有许多其他的窗口函数,本文列举一些,大家可以自行测试

类别

函数

说明

排序

ROW_NUMBER

为表中的每一行分配一个序号,可以指定分组(也可以不指定)及排序字段

DENSE_RANK

根据排序字段为每个分组中的每一行分配一个序号。 排名值相同时,序号相同,序号中没有间隙(1,1,2,3这种)

RANK

根据排序字段为每个分组中的每一行分配一个序号。 排名值相同时,序号相同,但序号中存在间隙(1,1,3,4这种)

NTILE

根据排序字段为每个分组中根据指定字段的排序再分成对应的组

分布

PERCENT_RANK

计算各分组或结果集中行的百分数等级

CUME_DIST

计算某个值在一组有序的数据中累计的分布

前后

LEAD

返回分组中当前行之后的第N行的值。如果不存在对应行,则返回NULL。比如N=1时,第一名对应的值是第二名的,最后一名结果是NULL

LAG

返回分组中当前行之前的第N行的值。如果不存在对应行,则返回NULL。比如N=1时,第一名对应的值是是NUL,最后一名结果是倒数第2的值

首尾中

FIRST_VALUE

返回每个分组中第一名对应的字段(或表达式)的值,例如本文中可以是第一名的分数、学号等任意字段的值

LAST_VALUE

返回每个分组中最后一名对应的字段(或表达式)的值,例如本文中可以是最后一名的分数、学号等任意字段的值

NTH_VALUE

返回每个分组中排名第N的对应字段(或表达式)的值,但小于N的行对应的值是NULL

MySQL中主要的窗口函数先总结这么多,建议还是得动手实践一番。另外,MySQL5.7及之前版本的排序方式的实现很多人已总结,也建议实操一番。

总结

到此这篇关于MySQL8.0窗口函数入门实践及总结的文章就介绍到这了,更多相关MySQL8.0窗口函数实践内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/573425.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MyEclipse Servers视窗出现“Could not create the view: An unexpected exception was thrown”错误解决办法...

MyEclipse 打开后有时候莫名的在server窗口里抛出“Could not create the view: An unexpected exception was thrown”错误,解决办法:打开myeclipse所在的wordspace文件夹,在下面子文件夹 .metadata\.plugins\org.eclipse.core.runtime\.set…

Java 入门基础

程序是为了让计算机执行某些操作或解决某个问题而编写的一系列有序指令的集合。Java是一门面向对象编程语言,不仅吸收了C语言的各种优点,还摒弃了C里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为…

mysql query cache 关闭_为什么要关闭MySQL query cache-Fun言

MySQL的query cache大部分情况下其实只是鸡肋而已,建议全面禁用。当然了,或许在你的场景下还是挺好的,还能发挥作用,那就继续使用吧,把本文当做参考就好。不过,可能有的人人为只需要把 query_cache_size 大…

Java 基础之java运算符

运算符,顾名思义就是用于计算的符号。按功能分为:赋值运算符、算术运算符、关系运算符和逻辑运算符按操作数的个数分类:单目运算符、双目运算符、三目运算符运算符的目:运算符能连接操作数的个数称为运算符的目运算符的优先级&…

直流电机调速仿真作业

本次调速仿真采用PID调节。首先要确定PID中的各项设计参数,仿真过程中采用临界比例度法确定了大概的Kp值。在若干次调整的过程中,发现加入微分环节后调整时间略有上升,故采用PI调节。调整参数确定为Kp75,Ki22。控制器部分的程序如下图所示。原…

mysql any 效率_关于mysql的性能优化

1.用 show status like value 查询mysql数据库性能2. 用 EXPLAIN select * from table 或 DESCRIBE select * from table 查看执行计划3.使用索引--使用 like关键字时 like %le索引不起作用,但 like le%索引可以起作用-- 使用关键字or时要求两个字段必须同为索引…

存储指针

- (void)addObserver:(__weak NSObject *)observer forContext:(void *)context { NSValue *valueContext [NSValue valueWithPointer:context]; dispatch_sync(self.queue, ^{ [self.trampolines setObject:observer forKey:valueContext]; }); }转载于:https://www.cnblogs.…

Java运算符优先级和表达式及数据类型转换

计算机程序在处理数据时会进行大量的计算,而数据的运算则需要借助运算符和表达式来完成。表达式是指由操作数和运算符组成的用于完成某种运算功能的语句子表达式Y X * ( Z 10 ) 表达式 其中Y、X、Z、10 称为操作数,、*、 称为运算符。 在…

Bugtags 2016-06-16 更新内容

增加版本管理功能 随着版本的增多,有些历史的版本不再使用,可将这些版本隐藏起来。操作步骤如下:点击设置 - 版本管理(管理员可见)- 取消勾选需要隐藏的版本即可。隐藏版本后,版本筛选中将不会显示&#xf…

MYSQL描述选课系统的问题与_mysql+php实现选课系统中遇到的问题及解决方法

首先是一些mysql 的基本命令删除表格 drop ;约束条件 :primary key 设置为主键unique 值唯一not null 非空foreighn key(key_name) references(key_name) 设置外键 default 设置默认值auto_increment 一般用于设置编号,随着…

Java 基础(条件结构)

Java 程序流程控制结构 顺序结构: 条件结构: 循环结构: 单分支if结构 选择 结构又称为分支结构 。 当 程序执行到分支判断的语句时,首先判断条件,然后根据条件表达式的结果选择相应的语句执行 。 分支 结构包括单分支、双分支和多分支三种形式。 语法…

直通车运营系统优化之账户结构设置

国庆期间,小2哥我好好的享受了好几天的日子,说实话,自从做了淘宝,就很少像这期间一样好好的享受了这段日子 。做淘宝有时候真的很苦逼,每天的工作时间比一个打工的还长,熬夜到凌晨才睡也是家常便饭&#xf…

mysql批量导入数据脚本_MySQL数据库批量导入脚本

//File: query.php//描述: 数据库批量导入脚本//功能: 可进行单行和批量插入.//作者: SworDs//QQ: 78623269//日期: 2005-1-21//其他:好老了啊,刚学PHP写的,连抄带查!2006.5.19从仓库里翻出来,。。。error_reporting(7);if ( function_exists…

原生JS封装ajax方法

http://blog.sucaijiayuan.com/article/89 jquery框架的ajax方法固然好用,但是假如某天我们的项目不能引入jquery或项目需求很简单,没有很多交互功能,只需要ajax,这时引入jquery库会造成资源浪费,也会显得页面臃肿。这…

mysql 从库 问题_一篇文章帮你解决Mysql 中主从库不同步的问题

写这篇文章是因为之前有一次删库操作,需要进行批量删除数据,当时没有控制好删除速度,导致产生了主从延迟,出现了一点小事故。今天我们就来看看为什么会产生主从延迟以及主从延迟如何处理等相关问题。坐好了,准备发车&a…

深度学习代码练习

代码下载地址:https://github.com/daijifeng001/R-FCN 对应论文:Object Detection via Region-based Fully Convolutional Networks 1、代码里面给的数据库下载链接失效,需要去代码下载主页最下方给定的资源区下载。 2、按照要求一步一步运行…

rabbitmq 不同的消费者消费同一个队列_消息队列王者--rabbitMQ深入理解--工作过程、消费模式、持久化等...

概述之前已经对rabbitMQ的一些基本概念做了介绍和不同MQ之间的比较,今天主要对rabbitMQ的一些方面做扩展。01消息队列Broker:简单来说就是消息队列服务器实体。Exchange:消息交换机,它指定消息按什么规则,路由到哪个队…

BZOJ 2763: [JLOI2011]飞行路线 spfa dp

题目链接&#xff1a; http://www.lydsy.com/JudgeOnline/problem.php?id2763 题解&#xff1a; d[x][kk]表示从s到x用了kk次免费机会的最少花费。 代码&#xff1a; #include<iostream> #include<cstdio> #include<algorithm> #include<queue> #incl…

mysql快速删除大表数据部分数据_mysql删除大表的部分数据

mysql删除大表的部分数据好久没写博客。最近项目要上线。下班时间还得陪着老妈。实在没时间更新。今天有人提了一个问题&#xff0c; www.2cto.com一个表有1亿6000万的数据&#xff0c;有一个自增ID。最大值就是1亿6000万&#xff0c;需要删除大于250万以后的数据&#xff0c;…

读“硬件抽象层:HAL”的心得

1 HAL是建立在Linux驱动上的一套程序库&#xff0c;并不属于Linux内核&#xff0c;而是属于Linux内核层上的应用层。它的目的就是保护“私人财产”&#xff0c;避免应用程序直接访问Linux驱动。 2在Android系统中使用Linux驱动有两种方式。一种就是通过传统的方式直接与Linux交…