Sql奇技淫巧之ROWNUM伪列

ROWNUM伪列

ROWNUM是一个伪列,它是根据每次查询的结果动态生成的一列递增编号,表示 Oracle 从表中选择该行的顺序,选择的第一行ROWNUM为1,第二行ROWNUM为2,以此类推。

注意1:

ROWNUM伪列是在WHERE子句之前生成的,就是说它并不是在执行了WHERE子句过滤之后再对数据编号

比如在执行WHERE子句,结果数据是这样的:

id name age ROWNUM
0001 mary 18 1
0002 mike 20 2
0003 john 19 3
0004 kitty 16 4
0005 susy 18 5
0006 echoo 21 6

这时候的ROWNUM是一列递增排列的、完整的编号

然后如果执行一个WHERE子句:WHERE age >18

那数据就变成了:

id name age ROWNUM
0002 mike 20 2
0003 john 19 3
0004 kitty 21 6

ROWNUM出现了断层,不连续了

如果后面再执行一个ORDER BY age DESC

就变成这样了:

id name age ROWNUM
0004 kitty 21 6
0002 mike 20 2
0003 john 19 3

ROWNUM不按顺序排了

所以在利用ROWNUM伪列来对结果集做限制、过滤、排序、分页等操作的时候一定要注意这个点,不然很容易错乱;

注意2:

ROWNUM是一行一行赋值的,只有上一行数据被选择成功,下一行才会递增!而且 select 语句也是一行一行选择的,每 select 一行数据就要进行 where 条件判断。

比如有这样一个employees表:

id name age
0001 mary 18
0002 mike 20
0003 john 19
0004 kitty 16
0005 susy 18
0006 echoo 21

对这个表执行这样一个SQL:

sql 复制代码
SELECT * FROM employees WHERE ROWNUM > 1;

这句SQL的预期为取出除第一条数据外的所有数据,但是执行的结果是一条都选不出来,来看执行过程:

① select 出的第一条数据为

id name age
0001 mary 18

ROWNUM 给这条数据赋值,因为是第一条数据,所以从 1 开始,赋值完是这样的:

id name age ROWNUM
0001 mary 18 1

③ 进行 WHERE ROWNUM > 1 条件判断,1>1不满足条件,所以第一条数据被过滤掉

④ select 第二条数据

id name age
0002 mike 20

ROWNUM 给这条数据赋值,因为上一条数据被过滤掉了,所以还是从 1 开始,赋值完是这样的:

id name age ROWNUM
0002 mike 20 1

⑥ 进行 WHERE ROWNUM > 1 条件判断,1>1不满足条件,所以这数据也被过滤掉

⑦ ·············

一直如此循环直到结束,都没有符合条件的数据,所以一条数据都选不出来!

例1:取前10条数据

ROWNUM来限制查询返回的行数,如下例所示:

sql 复制代码
SELECT * FROM employees WHERE ROWNUM < 11;

WHERE ROWNUM < 11表示返回查询数据的前10条;

例2:取排序后的前10条数据

不能够像下面这样直接在WHERE子句后简单的加上ORDER BY子句了

sql 复制代码
SELECT * FROM employees WHERE ROWNUM < 11 ORDER BY age;

因为这里的意思是先执行WHERE子句选出ROWNUM1~10的数据,然后再进行排列,和我们预想不符。我们要的是按年龄排序后的前10条数据。

所以应该这样写:

sql 复制代码
SELECT *
  FROM (SELECT * FROM employees ORDER BY employee_id)
  WHERE ROWNUM < 11;

这里的意思就是先执行排序,然后对排完序的结果集用ROWNUM伪列按顺序编号,然后取其中ROWNUM为1~10的那10条数据;

例3:分页

sql 复制代码
SELECT * 
FROM( SELECT temp_table.*,ROWNUM AS rn
  	  FROM (SELECT * FROM employees ORDER BY employee_id) temp_table
  	 ) result_table
WHERE result_table.rn BETWEEN 起始行数 AND 结尾行数

通过嵌套查询的方式,把动态的ROWNUM伪列变成固定的列rn,然后再用rn列进行分页;

相关推荐
人工智能训练2 分钟前
如何在 Ubuntu 22.04 中安装 Docker 引擎和 Linux 版 Docker Desktop 桌面软件
linux·运维·服务器·数据库·ubuntu·docker·ai编程
胖头鱼的鱼缸(尹海文)23 分钟前
数据库管理-第386期 使用OCP部署OceanBase 4.4.1社区版集群(20251107)
数据库·oceanbase
Craaaayon25 分钟前
如何选择两种缓存更新策略(写缓存+异步写库;写数据库+异步更新缓存)
java·数据库·redis·后端·缓存·mybatis
一 乐34 分钟前
点餐|智能点餐系统|基于java+ Springboot的动端的点餐系统小程序(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·小程序·论文
WarriorTan43 分钟前
理解PostgreSQL中的数据块
数据库·postgresql
学好statistics和DS1 小时前
三个好思路:SQL并行化处理、混淆矩阵和特征交叉
数据库·sql·矩阵
唐僧洗头爱飘柔95271 小时前
【GORM(3)】Go的跨时代ORM框架!—— 数据库连接、配置参数;本文从0开始教会如何配置GORM的数据库
开发语言·数据库·后端·golang·gorm·orm框架·dsn
谅望者2 小时前
在 macOS 上使用 Homebrew 安装 MySQL 8.0 完整指南
数据库·sql·mysql
程序员卷卷狗2 小时前
MySQL 页结构与数据存储原理全解析》
数据库·mysql
hweiyu002 小时前
MySQL 从入门到精通(视频教程)
数据库·mysql