Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Selecting the second row of a table using rownum

I have tried the below query:

select empno from (                    select empno                       from emp                     order by sal desc                   ) where rownum = 2 

This is not returning any records.

When I tried this query

 select rownum,empno from (                         select empno from emp order by sal desc)  

It gives me this output:

ROWNUM  EMPNO       1       7802         2       7809     3       7813     4       7823 

Can anyone tell me what's the problem with my first query? Why is it not returning any records when I add the ROWNUM filter?

like image 828
Gaurav Soni Avatar asked Feb 11 '12 12:02

Gaurav Soni


People also ask

How do you SELECT Rownum rows?

You can use ROWNUM to limit the number of rows returned by a query, as in this example: SELECT * FROM employees WHERE ROWNUM < 10; If an ORDER BY clause follows ROWNUM in the same query, then the rows will be reordered by the ORDER BY clause. The results can vary depending on the way the rows are accessed.

How do you fetch the second row in a table in Oracle?

For example, to find the second row in the scot. emp table when sorted by ename (and then, in case of a tie, empno), you can do this: WITH got_rnum AS( SELECT empno, ename, deptno -- or whatever you want , ROW_NUMBER () OVER ( ORDER BY ename , empno ) AS rnum FROM scott.

Why Rownum 2 is not valid in Oracle?

Oracle's ROWNUM starts on 1 and is only incremented when assigned to a row that passes the WHERE condition. Since you're filtering on ROWNUM=2, ROWNUM=1 doesn't pass the WHERE condition, and ROWNUM is therefore never assigned to a row and incremented to 2.


2 Answers

To explain this behaviour, we need to understand how Oracle processes ROWNUM. When assigning ROWNUM to a row, Oracle starts at 1 and only increments the value when a row is selected; that is, when all conditions in the WHERE clause are met. Since our condition requires that ROWNUM is greater than 2, no rows are selected and ROWNUM is never incremented beyond 1.

The bottom line is that conditions such as the following will work as expected.

.. WHERE rownum = 1;

.. WHERE rownum <= 10;

While queries with these conditions will always return zero rows.

.. WHERE rownum = 2;

.. WHERE rownum > 10;

Quoted from Understanding Oracle rownum

You should modify you query in this way in order to work:

select empno from     (     select empno, rownum as rn      from (           select empno           from emp           order by sal desc           )     ) where rn=2; 

EDIT: I've corrected the query to get the rownum after the order by sal desc

like image 145
Florin stands with Ukraine Avatar answered Oct 02 '22 03:10

Florin stands with Ukraine


In the first query, the first row will have ROWNUM = 1 so will be rejected. The second row will also have ROWNUM = 1 (because the row before was rejected) and also be rejected, the third row will also have ROWNUM = 1 (because all rows before it were rejected) and also be rejected etc... The net result is that all rows are rejected.

The second query should not return the result you got. It should correctly assign ROWNUM after ORDER BY.

As a consequence of all this, you need to use not 2 but 3 levels of subqueries, like this:

SELECT EMPNO, SAL FROM ( -- Make sure row is not rejected before next ROWNUM can be assigned.     SELECT EMPNO, SAL, ROWNUM R FROM ( -- Make sure ROWNUM is assigned after ORDER BY.         SELECT EMPNO, SAL         FROM EMP         ORDER BY SAL DESC     ) ) WHERE R = 2 

The result:

EMPNO                  SAL                     ---------------------- ----------------------  3                      7813                    
like image 44
Branko Dimitrijevic Avatar answered Oct 02 '22 03:10

Branko Dimitrijevic