模拟 ROW_NUMBER() 函数
时间:2022-07-22
本文章向大家介绍模拟 ROW_NUMBER() 函数,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
MySQL 在 8.0 的版本推出了窗口函数,我们可以很方便地使用 row_number()
函数生成序号。
比如,对于 emp
表,我们希望根据员工入职的时间排序,入职越早排在越前面,序号从 1 开始。使用 row_number()
就可以这么写:
SELECT
row_number() over (
ORDER BY hiredate) AS rn,
emp.*
FROM
emp
排序后的结果如下图所示:
图1 入职时间升序排序
再有,如果我们希望根据部门分组,再对每个组里面的员工按照入职时间升序排序。SQL 就这么写:
SELECT
row_number () over (
PARTITION BY deptno
ORDER BY hiredate
) AS rn,
emp.*
FROM
emp
ORDER BY deptno
对应的执行结果:
图2 组内按入职时间升序排序
那在 MySQL 8.0 版本之前呢,我们要怎么模拟 row_number()
函数?
方法还是比较多,接下来给大家展示一些经常用到的实现方法。
临时表 + 自增策略
如果没有分组的要求,可以创建于一个临时表,设置主键为 ,再增加一个字段,用来存储需要排序的表的主键(已根据条件排序)。原表和临时表一关联,临时表的主键就可以作为关联的结果的序号展示。
这种做法性能很好,不过只能应用于没有分组的场景。
用户变量
使用用户变量可以模拟大多数的窗口函数的功能,如果要实现上面图2 的效果,使用用户变量的写法要这样:
SELECT
rn,
empno,
ename,
job,
mgr,
hiredate,
sal,
comm,
deptno
FROM
(SELECT
@rn := IF(deptno = @deptno, @rn + 1, 1) AS rn,
emp.*,
@deptno := deptno
FROM
emp,
(SELECT
@deptno := NULL,
@rn := 1) b
ORDER BY deptno,
hiredate) t
使用用户变量模拟窗口函数需要注意两个地方:
- 排序,窗口函数里面用到分组、排序的字段,在使用用户变量的 SQL 中一定会出现在排序语句里面,而且是用于分组的字段排在前面;
- 赋值的表达式是
:=
,比较符号用=
,千万不能混用。
外连接
咱们又见到外连接了,外连接在这里可以这么用:
SELECT
COUNT(*) AS rn,a.*
FROM
emp a
LEFT JOIN emp b
ON b.deptno = a.deptno
AND a.hiredate >= b.hiredate
GROUP BY a.empno
ORDER BY deptno,1
结果中的序号是通过 count(*)
生成,简单介绍一下生成序号的算法:
取出一列数据,遍历列里面的每个数据,统计列中每个数小于或者等于它的个数。只要比较的字段没有重复数据,生成的序号就还是连续的。
标量子查询
不喜欢用外连接,也可以通过标量子查询生成序号。
SELECT
(SELECT
COUNT(*)
FROM
emp
WHERE deptno = a.deptno
AND hiredate <= a.hiredate) AS rn,
a.*
FROM
emp a
ORDER BY deptno,
1
要确保生成的序号无误,只需要清楚在关联的条件里一定是主表的 hiredate
字段的值大于关联表的 hiredate
的值。
写完后才发现之前已写过一篇类似的( SQL 窗口函数),想了想还是发出来,大家就当是温故知新了。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 触屏事件
- 10.2【前端开发】图片文件格式:常见的图片格式对比有何优劣以及如何使用Google的webp格式?
- uni-app 与 Vue H5 项目通讯
- Gridview][UpdateCommand的写法要点]
- MySQL系列之事务日志Undo log学习笔记
- click 延时解决方案
- Splash抓取javaScript动态渲染页面
- Sentence-Transformer的使用及fine-tune教程
- MySQL系列之事务日志Redo log学习笔记
- jQuery 的基本使用
- uni-app项目改用vue-cli npm运行报错及问题总汇
- 10.3【前端开发】背景图片:如何使用精灵图?
- Angular依赖注入官方文档的学习笔记
- jQuery 选择器
- MySQL系列之二进制日志Binlog学习笔记