有这么一张表:

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伪列未按预期取值导致的问题的更多相关文章

  1. Oracle中ROWNUM伪列和ROWID伪列的用法与区别

    做过Oracle分页的人都知道由于Oracle中没有像MySql中limit函数以及SQLServer中的top关键字等,所以只能通过伪列的方式去满足分页功能,在此,不谈分页方法,只从根本上去介绍这两 ...

  2. 1. 安装Oracle,配置环境 2. 实现查询From子句 3. 实现查询where子句 4. 实现查询order by子句

    一.环境安装1. 登录:以管理员身份登录 sqlplus 登录名/密码 管理员身份登录:sqlplus system/1234562. 登录后,导入案例.下载scott.sql文件,执行下面一行的命令 ...

  3. Oracle 中select XX_id_seq.nextval from dual 什么意思呢?

    说明 今天看别人的代码 ,遇见了 一条sql    select ctg_fault_list_id_seq.nextval from dual  不懂意思,然后就研究了下 dual :是oracle ...

  4. 论MySQL中如何代替Oracle中select into new_table from old_table

    v_receipt         warehouse_receipt%ROWTYPE;-- 这里创建表类型,v_receipt复刻了warehouse_receipt的类型(相当于拥有了所有相同的字 ...

  5. oracle中 SELECT INTO 和INSERT INTO ... SELECT区别

    在Oracle中,将一张表的数据复制到另外一个对象中.通常会有这两种方法:insert into select  和 select into from. 前者可以将select 出来的N行(0到任意数 ...

  6. Oracle中select使用别名

    1 .将字段用as转换成别名. 2 .直接在字段的名字后面跟别名. 3 .在字段后面用双引号引起的别名.   我的朋友 大鬼不动 最近访客 fhwlj kochiyas 大極星 Alz__ deser ...

  7. Oracle中select 1和select *的区别

    转自:https://www.linuxidc.com/Linux/2010-05/26202.htm 创建myt表并插入数据,如下: create table myt(name varchar2,c ...

  8. Oracle中Select语句完整的执行顺序

    oracle Select语句完整的执行顺序: .from 子句组装来自不同数据源的数据: .where 子句基于指定的条件对记录行进行筛选: .group by子句将数据划分为多个分组: .使用聚集 ...

  9. Hive中SELECT TOP N的方法(order by与sort by的区别)

    我想说的SELECT TOP N是取最大前N条或者最小前N条. Hive提供了limit关键字,再配合order by可以很容易地实现SELECT TOP N. 但是在Hive中order by只能使 ...

随机推荐

  1. Prometheus监控神器-Alertmanager篇(1)

    本章节主要涵盖了Alertmanager的工作机制与配置文件的比较详细的知识内容,由浅入深的给大家讲解. 警报一直是整个监控系统中的重要组成部分,Prometheus监控系统中,采集与警报是分离的.警 ...

  2. mybatis(mysql)代码生成器扩展

    前些天在做我的KSF框架的时候需要用到mybatis代码生成器, 但是发现有一些东西需要调整,主要集中在以下几点: 1. 加入batchInsert  2. 加入batchUpdate 3. mysq ...

  3. 「MoreThanJava」Day 5:面向对象进阶——继承详解

    「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」. 当然 ...

  4. java SFTP工具类

    需要导入jsch-0.1.52.jar import java.io.File; import java.io.FileInputStream; import java.io.FileOutputSt ...

  5. 2020-07-14:es用过冷热分离吗?假如现在有些数据热变冷,有些数据冷变热,怎么解决?

    福哥答案2020-07-14: 热变冷: 有x台机器tag设置为hot. 有y台机器tag设置为cool. hot集群中只存最近两天的. 有一个定时任务每天将前一天的索引标记为cool. es看到有新 ...

  6. python智能图片识别系统(图片切割、图片识别、区别标识)

    @ 目录 技术介绍 运行效果 关键代码 写在最后 技术介绍 你好! python flask图片识别系统使用到的技术有:图片背景切割.图片格式转换(pdf转png).图片模板匹配.图片区别标识. 运行 ...

  7. 用过 mongodb 吧, 这三个大坑踩过吗?

    一:背景 1. 讲故事 前段时间有位朋友在微信群问,在向 mongodb 中插入的时间为啥取出来的时候少了 8 个小时,8 在时间处理上是一个非常敏感的数字,又吉利又是一个普适的话题,后来我想想初次使 ...

  8. docker-machine在阿里云部署批量部署docker

    概述 docker入门中,docker swarm都是在本机的虚拟机上,为了更贴近生产环境,我将这部分重新部署到阿里云.不需要太贵,选最便宜的按量付费ECS,1小时才0.05元. docker-mac ...

  9. linux 查看系统页大小

    X86: [root@wangjq ~]# getconf PAGESIZE ARM: root@controller:~# getconf PAGESIZE

  10. 修改vsftpd的默认根目录/var/ftp/pub到另一个目录

    修改ftp的根目录只要修改/etc/vsftpd/vsftpd.conf文件即可: 加入如下几行: local_root=/var/www/html chroot_local_user=YES ano ...