Sql奇技淫巧之ROWNUM伪列的使用
作者:Echoo华地
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:
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
来限制查询返回的行数,如下例所示:
SELECT * FROM employees WHERE ROWNUM < 11;
WHERE ROWNUM < 11
表示返回查询数据的前10条;
例2:取排序后的前10条数据
不能够像下面这样直接在WHERE
子句后简单的加上ORDER BY
子句了
SELECT * FROM employees WHERE ROWNUM < 11 ORDER BY age;
因为这里的意思是先执行WHERE
子句选出ROWNUM
1~10的数据,然后再进行排列,和我们预想不符。我们要的是按年龄排序后的前10条数据。
所以应该这样写:
SELECT * FROM (SELECT * FROM employees ORDER BY employee_id) WHERE ROWNUM < 11;
这里的意思就是先执行排序,然后对排完序的结果集用ROWNUM
伪列按顺序编号,然后取其中ROWNUM
为1~10的那10条数据;
例3:分页
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
列进行分页;
到此这篇关于Sql奇技淫巧之ROWNUM伪列的文章就介绍到这了,更多相关Sql奇技淫巧之ROWNUM伪列内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!