Oracle中select子句取值先于order by子句执行而导致rownum伪列未按预期取值导致的问题
有这么一张表:
create table hytb(
id number(4,0) not null primary key,
padid nvarchar2(20) not null,
inputdate date not null,
dosid integer not null
)
可以这样给它充值:
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-23','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-24','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-25','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-26','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-23','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-24','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-25','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-27','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-24','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-25','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-24','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-25','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-28','yyyy-MM-dd'),'');
充完值是这样的结果集:

现在需要从中找出inputdate最近的三条记录(从图中目测是28-JAN-20,27-JAN-20,26-JAN-20),请问该怎么做?
首先可以利用row_number()函数:
select * from (select row_number() over (order by inputdate desc) as rn,hytb.* from hytb) a where a.rn<4

其次可以利用rownum伪列:
select * from (select rownum as rn,a.* from (select * from hytb order by inputdate desc) a) b where b.rn<4

这两种SQL都是正确的,可以互相验证。
但是,下面的sql却是错误的:
select * from (select rownum as rn,hytb.* from hytb order by inputdate desc) a where a.rn<4
执行结果如下:

为什么会出现这样的结果呢,让我们先看看其中子句select rownum as rn,hytb.* from hytb order by inputdate desc的执行结果:

可以发现,伪列和id是一样的,并没有按时间排。
究其原因,是因为select子句的执行顺序在order by之前,在sql:
select rownum as rn,hytb.* from hytb order by inputdate desc
里,首先执行的是
select rownum as rn,hytb.* from hytb
其次才是
order by inputdate desc
也就是说,伪列先于order by执行,或者说 select子句先于order by子句执行,由于rownum在select子句中,所以rownum伪列先于order by执行。
关于SQL子句的执行顺序,可以参考:https://database.51cto.com/art/202001/609727.htm

这就是问题所在。
突破藩篱的感觉真好。
--2020-03-10--
以下是上面实验用到的所有sql,贴出来以供参考:
create table hytb(
id number(4,0) not null primary key,
padid nvarchar2(20) not null,
inputdate date not null,
dosid integer not null
) insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-23','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-24','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-25','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-26','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-23','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-24','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-25','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-27','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-24','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-25','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-24','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-25','yyyy-MM-dd'),'');
insert into hytb(id,padid,inputdate,dosid) values('','',to_date('2020-01-28','yyyy-MM-dd'),''); commit; truncate table hytb select * from hytb --Correct
select * from (select rownum as rn,a.* from (select * from hytb order by inputdate desc) a) b where b.rn<4 select * from (select row_number() over (order by inputdate desc) as rn,hytb.* from hytb) a where a.rn<4 --Wrong
select * from (select rownum as rn,hytb.* from hytb order by inputdate desc) a where a.rn<4
Oracle中select子句取值先于order by子句执行而导致rownum伪列未按预期取值导致的问题的更多相关文章
- Oracle中ROWNUM伪列和ROWID伪列的用法与区别
做过Oracle分页的人都知道由于Oracle中没有像MySql中limit函数以及SQLServer中的top关键字等,所以只能通过伪列的方式去满足分页功能,在此,不谈分页方法,只从根本上去介绍这两 ...
- 1. 安装Oracle,配置环境 2. 实现查询From子句 3. 实现查询where子句 4. 实现查询order by子句
一.环境安装1. 登录:以管理员身份登录 sqlplus 登录名/密码 管理员身份登录:sqlplus system/1234562. 登录后,导入案例.下载scott.sql文件,执行下面一行的命令 ...
- Oracle 中select XX_id_seq.nextval from dual 什么意思呢?
说明 今天看别人的代码 ,遇见了 一条sql select ctg_fault_list_id_seq.nextval from dual 不懂意思,然后就研究了下 dual :是oracle ...
- 论MySQL中如何代替Oracle中select into new_table from old_table
v_receipt warehouse_receipt%ROWTYPE;-- 这里创建表类型,v_receipt复刻了warehouse_receipt的类型(相当于拥有了所有相同的字 ...
- oracle中 SELECT INTO 和INSERT INTO ... SELECT区别
在Oracle中,将一张表的数据复制到另外一个对象中.通常会有这两种方法:insert into select 和 select into from. 前者可以将select 出来的N行(0到任意数 ...
- Oracle中select使用别名
1 .将字段用as转换成别名. 2 .直接在字段的名字后面跟别名. 3 .在字段后面用双引号引起的别名. 我的朋友 大鬼不动 最近访客 fhwlj kochiyas 大極星 Alz__ deser ...
- Oracle中select 1和select *的区别
转自:https://www.linuxidc.com/Linux/2010-05/26202.htm 创建myt表并插入数据,如下: create table myt(name varchar2,c ...
- Oracle中Select语句完整的执行顺序
oracle Select语句完整的执行顺序: .from 子句组装来自不同数据源的数据: .where 子句基于指定的条件对记录行进行筛选: .group by子句将数据划分为多个分组: .使用聚集 ...
- Hive中SELECT TOP N的方法(order by与sort by的区别)
我想说的SELECT TOP N是取最大前N条或者最小前N条. Hive提供了limit关键字,再配合order by可以很容易地实现SELECT TOP N. 但是在Hive中order by只能使 ...
随机推荐
- SpringBoot整合Spring Security
好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 前言 Spring Securi ...
- Docker服务开放了这个端口,服务器分分钟变肉机
之前有很多朋友提过,当使用docker-maven-plugin打包SpringBoot应用的Docker镜像时,服务器需要开放2375端口.由于开放了端口没有做任何安全保护,会引起安全漏洞,被人入侵 ...
- PythonCrashCourse 第四章习题
Python 从入门到实践第四章习题 4.1想出至少三种你喜欢的比萨,将其名称存储在一个列表中,再使用for 循环将每种比萨的名称都打印出来 修改这个for 循环,使其打印包含比萨名称的句子,而不仅仅 ...
- C++统计单词数
[题目描述] 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数.现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在 ...
- MySQL SQL概述
MySQL SQL概述 数据库的好处: •实现数据持久化 •使用完整的管理系统统一管理易 数据库的概念: DB:数据库(database):存储数据的“仓库”.它保存了一系列有组织的数据. DBMS: ...
- HDFS的数据流读写数据 (面试开发重点)
1 HDFS写数据流程 1.1 剖析文件写入 HDFS写数据流程,如图所示 1)客户端通过Distributed FileSystem模块向NameNode请求上传文件,NameNode检查目标文件是 ...
- 随机陷阱和P值
如果让大家写一个50次的抛硬币实验的可能结果(头像H或字T),多半人在连续三个一样的后,会换一下.因为大家都知道,连续一样的越多,概率越小,越不可能发生.大部分人不会去想,其实HHHTT和HHHHH发 ...
- 结构体深度比较 reflect.DeepEqual
demo1 package main import ( "fmt" "reflect" ) func main() { sliceMap1 := make([] ...
- Python之运维
这几日一直研究运维监控的事情,有次看见有一个脚本写的还不错,如今已经找不到地址了 就只能用Python代替shell了 其中原理是 监控 /proc/下的各种文件,/proc/ 顾名思义其为进程的文件 ...
- [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
Linux下安装MySQL执行scripts/mysql_install_db --user=mysql脚本时,报错如下: Filling help tables...2019-12-24 16:46 ...