有这么一张表:

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. GitLab 查看版本号

    cat /opt/gitlab/embedded/service/gitlab-rails/VERSION

  2. linux7手动添加systemctl启动程序

    1.路径 [root@angrymushrooms01 system]# pwd /usr/lib/systemd/system 2.脚本内容 vim xxx.service ------------ ...

  3. Web测试转App测试不看不知道

    Web测试 Web通常指的是互联网应用系统,比如税务电子化征管档案系统.金融数据平台.餐饮商家管理后台等等,其实质是C/S的程序. C是Client--客户端,S是Server--服务器. Web中的 ...

  4. JS学习第三天

    运算符: 赋值运算符 “=” ,将“=”右边的值赋值给左边 比较运算符 “>   <   >=  <=   ==   !=   ===”,  ==比较两边内容是否一致      ...

  5. 2020-04-06:insert语句在mysql里经历了什么?

    1.会话状态转换为update 2.激活事物状态由 not_active 变为 active 3.查找定位数据 4.进行乐观插入 记录insert的undo记录记录undo的redo log 入red ...

  6. C#LeetCode刷题之#501-二叉搜索树中的众数​​​​​​​(Find Mode in Binary Search Tree)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4086 访问. 给定一个有相同值的二叉搜索树(BST),找出 BS ...

  7. C#LeetCode刷题之#104-二叉树的最大深度​​​​​​​(Maximum Depth of Binary Tree)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4072 访问. 给定一个二叉树,找出其最大深度. 二叉树的深度为根 ...

  8. C#设计模式之21-策略模式

    策略模式(Stragety Pattern) 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/427 访问. 策略模式属于 ...

  9. 自己动手编写一个Mybatis插件:Mybatis脱敏插件

    1. 前言 在日常开发中,身份证号.手机号.卡号.客户号等个人信息都需要进行数据脱敏.否则容易造成个人隐私泄露,客户资料泄露,给不法分子可乘之机.但是数据脱敏不是把敏感信息隐藏起来,而是看起来像真的一 ...

  10. PostgreSQL在没有备份情况下误删除Clog恢复

    创建实验表postgres# create table t (n_id int primary key,c_name varchar(300));CREATE TABLEpostgres# inser ...