有这么一张表:
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('1','001',to_date('2020-01-23','yyyy-MM-dd'),'398'); insert into hytb(id,padid,inputdate,dosid) values('2','001',to_date('2020-01-24','yyyy-MM-dd'),'442'); insert into hytb(id,padid,inputdate,dosid) values('3','001',to_date('2020-01-25','yyyy-MM-dd'),'90'); insert into hytb(id,padid,inputdate,dosid) values('4','001',to_date('2020-01-26','yyyy-MM-dd'),'178'); insert into hytb(id,padid,inputdate,dosid) values('5','002',to_date('2020-01-23','yyyy-MM-dd'),'444'); insert into hytb(id,padid,inputdate,dosid) values('6','002',to_date('2020-01-24','yyyy-MM-dd'),'15'); insert into hytb(id,padid,inputdate,dosid) values('7','002',to_date('2020-01-25','yyyy-MM-dd'),'145'); insert into hytb(id,padid,inputdate,dosid) values('8','002',to_date('2020-01-27','yyyy-MM-dd'),'196'); insert into hytb(id,padid,inputdate,dosid) values('9','003',to_date('2020-01-24','yyyy-MM-dd'),'22'); insert into hytb(id,padid,inputdate,dosid) values('10','003',to_date('2020-01-25','yyyy-MM-dd'),'22'); insert into hytb(id,padid,inputdate,dosid) values('11','004',to_date('2020-01-24','yyyy-MM-dd'),'33'); insert into hytb(id,padid,inputdate,dosid) values('12','004',to_date('2020-01-25','yyyy-MM-dd'),'33'); insert into hytb(id,padid,inputdate,dosid) values('13','004',to_date('2020-01-28','yyyy-MM-dd'),'33');
充完值是这样的结果集:
现在需要从中找出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('1','001',to_date('2020-01-23','yyyy-MM-dd'),'398'); insert into hytb(id,padid,inputdate,dosid) values('2','001',to_date('2020-01-24','yyyy-MM-dd'),'442'); insert into hytb(id,padid,inputdate,dosid) values('3','001',to_date('2020-01-25','yyyy-MM-dd'),'90'); insert into hytb(id,padid,inputdate,dosid) values('4','001',to_date('2020-01-26','yyyy-MM-dd'),'178'); insert into hytb(id,padid,inputdate,dosid) values('5','002',to_date('2020-01-23','yyyy-MM-dd'),'444'); insert into hytb(id,padid,inputdate,dosid) values('6','002',to_date('2020-01-24','yyyy-MM-dd'),'15'); insert into hytb(id,padid,inputdate,dosid) values('7','002',to_date('2020-01-25','yyyy-MM-dd'),'145'); insert into hytb(id,padid,inputdate,dosid) values('8','002',to_date('2020-01-27','yyyy-MM-dd'),'196'); insert into hytb(id,padid,inputdate,dosid) values('9','003',to_date('2020-01-24','yyyy-MM-dd'),'22'); insert into hytb(id,padid,inputdate,dosid) values('10','003',to_date('2020-01-25','yyyy-MM-dd'),'22'); insert into hytb(id,padid,inputdate,dosid) values('11','004',to_date('2020-01-24','yyyy-MM-dd'),'33'); insert into hytb(id,padid,inputdate,dosid) values('12','004',to_date('2020-01-25','yyyy-MM-dd'),'33'); insert into hytb(id,padid,inputdate,dosid) values('13','004',to_date('2020-01-28','yyyy-MM-dd'),'33'); 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