MySQL实现Oracle rank()排序
一、Oracle写法介绍
MySQL5.7版本没有提供类似Oracle的分析函数,比如开窗函数over(...),oracle开窗函数over(...)使用的话一般是和order、partition by、row_number()、rank()、dense_rank()几个函数一起使用,具体的用法可以参考我之前的博客oracle开窗函数用法简介
假如要获取成绩排序第一的学生信息,可以用如下的SQL:
select *
from (select stuId, stuName, classId,
row_number() over(partition by classId order by score desc) rn
from t_score)
where rn = 1;
二、Oracle和MySQL写法对比
ok,就用学生成绩排名的例子
学号 | 姓名 | 班级 | 成绩 |
---|---|---|---|
111 | 小王 | 1 | 92 |
123 | 小李 | 2 | 90 |
134 | 小钱 | 3 | 92 |
145 | 小顺 | 4 | 100 |
数据表为t_score,字段分别为stuId,stuName,classId ,score
环境准备,先建表,写数据:
#成绩表
CREATE TABLE t_score(
stuId VARCHAR(20),
stuName VARCHAR(50),
classId INT,
score FLOAT
);
# 写数据
INSERT INTO t_score(stuId,stuName,classId,score) VALUES('111','小王',2,92);
INSERT INTO t_score(stuId,stuName,classId,score) VALUES('123','小李',1,90);
INSERT INTO t_score(stuId,stuName,classId,score) VALUES('134','小钱',1,92);
INSERT INTO t_score(stuId,stuName,classId,score) VALUES('145','小顺',2,100);
然后给出sql,用的是临时变量的方法:
SELECT
IF(
@classId := c.classId,
@rn := @rn + 1,
@rn := 1
) AS rn,
c.stuId,
c.stuName,
c.classId,
c.score ,
@classId := c.classId
FROM
(SELECT
stuId,
stuName,
classId,
score
FROM
t_score
ORDER BY score ASC) c,
(SELECT
@rn := 0,
@classId := NULL) r ;
不过对于上面的写法,这里也进行分析,让学习者可以更好理解,因为很多地方都是直接贴代码,不写明原因,对于入门者来说,可能都不理解
用执行计划来解释:
加上Explain,对于执行计划不熟悉的学习者可以参考我之前博客:MySQL Explain学习笔记
从执行计划可以看出:
- ①、上面SQL,执行时候是先执行这条衍生查询SQL,
SELECT @rn := 0,@classId := NULL
,这个其实是为了初始化临时变量@rn和@classId - ②、执行查询t_score,
SELECT stuId, stuName,classId,score FROM t_score ORDER BY score ASC
,同样是返回一个衍生表 - ③、主查询1,
SELECT @rn := 0,@classId := NULL
衍生查询完成后,进行别名为r的主查询
- ④、同理,主查询2,衍生查询
SELECT stuId, stuName,classId,score FROM t_score ORDER BY score ASC
查询成功后,在进行外面的主查询,也就是对别名为c的主表查询
所以网上这种写法也是值得学习的,一种是利用了mysql的执行计划执行顺序对临时变量进行赋值,然后再用临时变量进行叠加,写法还是值得学习的
对于临时变量的知识点,可以参考我之前博客:MySQL变量学习笔记
注意:这里网上有很多这种写法,不过我验证了,并不能实现了oracle类似的partition by效果,也就是没分组效果,也有可能是哪里写错了,欢迎指出!
MySQL实现的效果:
Oracle实现的效果:
很显然,如图如比对所示,在oracle里,不仅分组了,而且rn也按照班级进行排名,Oracle实现的效果显然和网上很多地方提出的这种写法效果是不一样的,网上的这种写法仅仅是进行排序而已,并没有按照班级进行分组排名
上面都是自己动手验证过,目的是指出网上很多地方的这种写法是不正确的,或许也有可能是自己写错哪里了,都欢迎指出!
所以,对于Oracle rank()、row_number加上开窗函数进行排序,并没有partition by分组的时候,是可以用这种方法,不过写法要改一下,代码如:
SELECT
/* IF(
@classId := c.classId
AND @score := c.score,
@rn := @rn + 1,
@rn := 1
) AS rn,*/
rn := @rn+1 as rn,
c.stuId,
c.stuName,
c.classId,
c.score ,
@classId := c.classId
FROM
(SELECT
stuId,
stuName,
classId,
score
FROM
t_score
ORDER BY score ASC,classId) c,
(SELECT
@rn := 0,
@classId := NULL) r ;
MySQL实现Oracle rank()排序的更多相关文章
- 【转】MySQL实现Oracle里的 rank()over(ORDER BY) 功能
Oracle rank()和dense_rank()的区别是: –rank()是跳跃排序,有两个第二名时接下来就是第四名 –dense_rank()l是连续排序,有两个第二名时仍然跟着第三名 sele ...
- MySQL、Oracle和SQL Server的分页查询语句
假设当前是第PageNo页,每页有PageSize条记录,现在分别用Mysql.Oracle和SQL Server分页查询student表. 1.Mysql的分页查询: SELECT * FROM s ...
- MySQL与Oracle的区别
1.语法上的区别 变量类型定义.IN OUT的位置.变量定义的位置.游标的位置.异常的位置: 2.MySQL没有 return 关键字,采用leave label的方式结束循环或跳出存储 3.异常处 ...
- 在MySQL中实现Rank高级排名函数【转】
MySQL中没有Rank排名函数,当我们需要查询排名时,只能使用MySQL数据库中的基本查询语句来查询普通排名.尽管如此,可不要小瞧基础而简单的查询语句,我们可以利用其来达到Rank函数一样的高级排名 ...
- 在MySQL中实现Rank高级排名函数
MySQL中没有Rank排名函数,当我们需要查询排名时,只能使用MySQL数据库中的基本查询语句来查询普通排名.尽管如此,可不要小瞧基础而简单的查询语句,我们可以利用其来达到Rank函数一样的高级排名 ...
- mysql 等 null 空值排序
[sqlserver]: sqlserver 认为 null 最小. 升序排列:null 值默认排在最前. 要想排后面,则:order by case when col is null then 1 ...
- MySQL与Oracle的语法区别详细对比
MySQL与Oracle的语法区别详细对比 Oracle和mysql的一些简单命令对比在本文中将会涉及到很多的实例,感兴趣的你不妨学习一下,就当巩固自己的知识了 Oracle和mysql的一些简单 ...
- 【软件实施面试】MySQL和Oracle联合查询以及聚合函数面试总结
软件实施面试系列文章第二弹,MySQL和Oracle联合查询以及聚合函数的面试总结.放眼望去全是MySQL,就不能来点Oracle吗?之前面过不少公司,也做过不少笔试题,现在已经很少做笔试题了.你肚子 ...
- 【无私分享:ASP.NET CORE 项目实战(第十二章)】添加对SqlServer、MySql、Oracle的支持
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 增加对多数据库的支持,并不是意味着同时对多种数据库操作,当然,后面,我们会尝试同时对多种数据库操作,这可能需要多个上下文,暂且 ...
随机推荐
- tk.mybatis扩展通用接口
一.tk.mybatis已经为我们封装好了许多拆箱即用的通用mapper,但在实际的项目开发中想必不少小伙伴在数据库设计中都会采用逻辑删除这种方案,再去使用通用的mapper接口就不行了.这时候就需要 ...
- 100天搞定机器学习|day39 Tensorflow Keras手写数字识别
提示:建议先看day36-38的内容 TensorFlow™ 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库.节点(Nodes)在图中表示数学操作,图中的线(edge ...
- 用gcc/g++编译winsock程序
用gcc/g++编译winsock程序 D:\My\code>gcc -o getweb.exe getweb.c -lwin32socket 如果不加此句 -lwin32socket 编译会报 ...
- 真正加速Jenkins安装插件速度
本文主旨 看到好多加速Jenkins安装插件速度的文章, 大多数教程中都是在插件配置里使用下边的url来替换原有的https://mirrors.tuna.tsinghua.edu.cn/jenkin ...
- SpringBoot_@valid_参数校验
SpringBoot @valid 参数校验 空检查 @Null 验证对象是否为null @NotNull 验证对象是否不为null, 无法查检长度为0的字符串 @NotBlank 检查约束字符串是不 ...
- Python之流程控制——while循环
Python之流程控制--while循环 一.语法 while 条件: 执行代码 while就是当的意思,它指当其后面的条件成立,就执行while下面的代码. 例:写一个从0打印到10的程序 coun ...
- netty源码解解析(4.0)-20 ChannelHandler: 自己实现一个自定义协议的服务器和客户端
本章不会直接分析Netty源码,而是通过使用Netty的能力实现一个自定义协议的服务器和客户端.通过这样的实践,可以更深刻地理解Netty的相关代码,同时可以了解,在设计实现自定义协议的过程中需要解决 ...
- CodeForces gym Nasta Rabbara lct
Nasta Rabbara 题意:简单来说就是, 现在有 n个点, m条边, 每次询问一个区间[ l , r ], 将这个区间的所有边都连上, 如果现在的图中有奇数环, 就输出 “Impossibl ...
- CODE[VS] 3269 混合背包
3269 混合背包 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 背包体积为V ,给出N ...
- 洛谷 P1666 前缀单词 题解
题意:给n个单词,如果单词a为单词b的前缀则a,b不能共存,问能共存的集合数(包括空集) 一道dp题,排序后判断,f[i][j]表示i和j是否能共存,f[i][j]=1表示能共存,初始化dp[i]=1 ...