一、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()排序的更多相关文章

  1. 【转】MySQL实现Oracle里的 rank()over(ORDER BY) 功能

    Oracle rank()和dense_rank()的区别是: –rank()是跳跃排序,有两个第二名时接下来就是第四名 –dense_rank()l是连续排序,有两个第二名时仍然跟着第三名 sele ...

  2. MySQL、Oracle和SQL Server的分页查询语句

    假设当前是第PageNo页,每页有PageSize条记录,现在分别用Mysql.Oracle和SQL Server分页查询student表. 1.Mysql的分页查询: SELECT * FROM s ...

  3. MySQL与Oracle的区别

    1.语法上的区别 变量类型定义.IN  OUT的位置.变量定义的位置.游标的位置.异常的位置: 2.MySQL没有 return 关键字,采用leave label的方式结束循环或跳出存储 3.异常处 ...

  4. 在MySQL中实现Rank高级排名函数【转】

    MySQL中没有Rank排名函数,当我们需要查询排名时,只能使用MySQL数据库中的基本查询语句来查询普通排名.尽管如此,可不要小瞧基础而简单的查询语句,我们可以利用其来达到Rank函数一样的高级排名 ...

  5. 在MySQL中实现Rank高级排名函数

    MySQL中没有Rank排名函数,当我们需要查询排名时,只能使用MySQL数据库中的基本查询语句来查询普通排名.尽管如此,可不要小瞧基础而简单的查询语句,我们可以利用其来达到Rank函数一样的高级排名 ...

  6. mysql 等 null 空值排序

    [sqlserver]: sqlserver 认为 null 最小. 升序排列:null 值默认排在最前. 要想排后面,则:order by case when col is null then 1 ...

  7. MySQL与Oracle的语法区别详细对比

    MySQL与Oracle的语法区别详细对比 Oracle和mysql的一些简单命令对比在本文中将会涉及到很多的实例,感兴趣的你不妨学习一下,就当巩固自己的知识了   Oracle和mysql的一些简单 ...

  8. 【软件实施面试】MySQL和Oracle联合查询以及聚合函数面试总结

    软件实施面试系列文章第二弹,MySQL和Oracle联合查询以及聚合函数的面试总结.放眼望去全是MySQL,就不能来点Oracle吗?之前面过不少公司,也做过不少笔试题,现在已经很少做笔试题了.你肚子 ...

  9. 【无私分享:ASP.NET CORE 项目实战(第十二章)】添加对SqlServer、MySql、Oracle的支持

    目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 增加对多数据库的支持,并不是意味着同时对多种数据库操作,当然,后面,我们会尝试同时对多种数据库操作,这可能需要多个上下文,暂且 ...

随机推荐

  1. PKI机制总结

    PKI,全称是Public Key Infrastructure,可译为公钥基础设施.它是因特网中节点通信的安全保障机制,HTTPS中的‘S’就来源于PKI. 要去学习一个技术,首先要从它的源头考虑— ...

  2. java字符串详解

    一.String 类的定义 public final class String implements java.io.Serializable, Comparable<String>, C ...

  3. LD_PRELOAD和ld --wrap

    前言 LD_PRELOAD和ld --wrap都能实现不修改原始代码,替换指定函数的实现.通常我们会使用这些方法,替换如malloc)()/free().read()/write()等函数,并在替换函 ...

  4. python匿名函数的介绍及用途

    匿名函数 用lambda能够创建一个匿名函数,这中函数得名于省略了用def声明函数的标准步骤. 语法 lambda [arg1 [,arg2,.....argn]]:expression 如何使用 我 ...

  5. net core Webapi基础工程搭建(五)——缓存机制

    目录 前言 Cache Session Cookie 小结 补充 前言 作为WebApi接口工程,性能效率是必不可少的,每次的访问请求,数据库读取,业务逻辑处理都或多或少耗费时间,偶尔再来个各种花式f ...

  6. 2019-SUCTF-web记录

    1.web1-chkin 首先发现服务器中间件为nginx,并且fuzz上传过滤情况,是黑名单,带ph的全部不能上传切对文件内容中包含<?进行过滤,并且服务器对文件头有exif_type的判断, ...

  7. js中更改this指向 以及回顾bind、call和apply

    1.更改this指向 方法1:对this进行保存            var _this = this; 例: var _this = this;     document.onclick = fu ...

  8. 第五章 函数day2

    5.2函数小高级 5.2.1 函数当参数 1 函数也可以当返回值 def v(dar): v = dar() def n (): print(444) v(n) # 实例2 def v(): prin ...

  9. Java集合框架之HashMap浅析

    Java集合框架之HashMap浅析 一.HashMap综述: 1.1.HashMap概述 位于java.util包下的HashMap是Java集合框架的重要成员,它在jdk1.8中定义如下: pub ...

  10. 基于Taro与typescript开发的网易云音乐小程序(持续更新)

    基于Taro与网易云音乐api开发,技术栈主要是:typescript+taro+taro-ui+redux,目前主要是着重小程序端的展示,主要也是借此项目强化下上述几个技术栈的使用,通过这个项目也可 ...