9

There is a clear answer how to select top 1:

select * from table_name where rownum = 1

and how to order by date in descending order:

select * from table_name order by trans_date desc

but they does not work togeather (rownum is not generated according to trans_date):

... where rownum = 1 order by trans_date desc

The question is how to select top 1 also ordered by date?

Ivan Gerasimenko
  • 2,138
  • 2
  • 20
  • 44
  • @MT0 , this is not a duplicate of **"How do I do top 1 in Oracle?"** and **"Oracle SELECT TOP 10 records"** because they are just about limited number of rows in result of a query, and not about ordering. As you can see I refer to the first question in the first line of mine. – Ivan Gerasimenko Jun 08 '17 at 13:08
  • "How do I do top 1 in Oracle?" all the answers apart from the accepted one show how to order the result set and get the first ordered result. "Oracle SELECT TOP 10 records" the OP explicitly asks why they are getting random rows rather than the top ordered rows. They are duplicates. – MT0 Jun 08 '17 at 13:11
  • BTW, I can not delete the question because it's prohibited by system: some people have already answered it – Ivan Gerasimenko Jun 08 '17 at 13:12
  • this one has the best answer. – Jim May 28 '19 at 10:36

4 Answers4

34
... where rownum = 1 order by trans_date desc

This selects one record arbitrarily chosen (where rownum = 1) and then sorts this one record (order by trans_date desc).

As shown by Ivan you can use a subquery where you order the records and then keep the first record with where rownum = 1in the outer query. This, however, is extremely Oracle-specific and violates the SQL standard where a subquery result is considered unordered (i.e. the order by clause can be ignored by the DBMS).

So better go with the standard solution. As of Oracle 12c:

select * 
from table_name 
order by trans_date desc
fetch first 1 row only;

In older versions:

select *
from
(
  select t.*, row_number() over (order by trans_date desc) as rn
  from table_name t
)
where rn = 1;
Thorsten Kettner
  • 69,709
  • 4
  • 37
  • 58
2

Modern Oracle versions have FETCH FIRST:

select * from table_name order by trans_date desc
fetch first 1 row only
jarlh
  • 35,821
  • 8
  • 33
  • 49
1

There should be subquery so the combination rownum & order could work:

select * from (select * from table_name order by trans_date desc) AS tb where rownum = 1
Ivan Gerasimenko
  • 2,138
  • 2
  • 20
  • 44
1

You can use window functions for that:

select t.*
from (
  select *, 
         min(trans_date) over () as min_date,
         max(trans_date) over () as max_date
  from the_table 
) t 
where trans_date = min_date 
   or trans_date = max_date;

Another option would be to join on the derived table

select t1.*
from the_table 
  join ( 
    select min(trans_date) over () as min_date,
           max(trans_date) over () as max_date
    from the_table
) t2 on t1.trans_date = t2.min_date 
     or t1.trans_date = t2.max_date;

Not sure which one would be faster, you need to check the execution plan

a_horse_with_no_name
  • 440,273
  • 77
  • 685
  • 758