How do I limit the number of rows returned by an Oracle query after ordering?

前端 未结 17 1472
夕颜
夕颜 2020-11-21 04:56

Is there a way to make an Oracle query behave like it contains a MySQL limit clause?

In MySQL, I can do this:

         


        
相关标签:
17条回答
  • 2020-11-21 05:11

    I'v started preparing for Oracle 1z0-047 exam, validated against 12c While prepping for it i came across a 12c enhancement known as 'FETCH FIRST' It enables you to fetch rows /limit rows as per your convenience. Several options are available with it

    - FETCH FIRST n ROWS ONLY
     - OFFSET n ROWS FETCH NEXT N1 ROWS ONLY // leave the n rows and display next N1 rows
     - n % rows via FETCH FIRST N PERCENT ROWS ONLY
    

    Example:

    Select * from XYZ a
    order by a.pqr
    FETCH FIRST 10 ROWS ONLY
    
    0 讨论(0)
  • 2020-11-21 05:13

    I did some performance testing for the following approaches:

    Asktom

    select * from (
      select a.*, ROWNUM rnum from (
        <select statement with order by clause>
      ) a where rownum <= MAX_ROW
    ) where rnum >= MIN_ROW
    

    Analytical

    select * from (
      <select statement with order by clause>
    ) where myrow between MIN_ROW and MAX_ROW
    

    Short Alternative

    select * from (
      select statement, rownum as RN with order by clause
    ) where a.rn >= MIN_ROW and a.rn <= MAX_ROW
    

    Results

    Table had 10 million records, sort was on an unindexed datetime row:

    • Explain plan showed same value for all three selects (323168)
    • But the winner is AskTom (with analytic following close behind)

    Selecting first 10 rows took:

    • AskTom: 28-30 seconds
    • Analytical: 33-37 seconds
    • Short alternative: 110-140 seconds

    Selecting rows between 100,000 and 100,010:

    • AskTom: 60 seconds
    • Analytical: 100 seconds

    Selecting rows between 9,000,000 and 9,000,010:

    • AskTom: 130 seconds
    • Analytical: 150 seconds
    0 讨论(0)
  • 2020-11-21 05:17

    An analytic solution with only one nested query:

    SELECT * FROM
    (
       SELECT t.*, Row_Number() OVER (ORDER BY name) MyRow FROM sometable t
    ) 
    WHERE MyRow BETWEEN 10 AND 20;
    

    Rank() could be substituted for Row_Number() but might return more records than you are expecting if there are duplicate values for name.

    0 讨论(0)
  • 2020-11-21 05:17

    If you are not on Oracle 12C, you can use TOP N query like below.

    SELECT *
     FROM
       ( SELECT rownum rnum
              , a.*
           FROM sometable a 
       ORDER BY name
       )
    WHERE rnum BETWEEN 10 AND 20;
    

    You can even move this from clause in with clause as follows

    WITH b AS
    ( SELECT rownum rnum
          , a.* 
       FROM sometable a ORDER BY name
    ) 
    SELECT * FROM b 
    WHERE rnum BETWEEN 10 AND 20;
    

    Here actually we are creating a inline view and renaming rownum as rnum. You can use rnum in main query as filter criteria.

    0 讨论(0)
  • 2020-11-21 05:19

    Pagination queries with ordering are really tricky in Oracle.

    Oracle provides a ROWNUM pseudocolumn that returns a number indicating the order in which the database selects the row from a table or set of joined views.

    ROWNUM is a pseudocolumn that gets many people into trouble. A ROWNUM value is not permanently assigned to a row (this is a common misunderstanding). It may be confusing when a ROWNUM value is actually assigned. A ROWNUM value is assigned to a row after it passes filter predicates of the query but before query aggregation or sorting.

    What is more, a ROWNUM value is incremented only after it is assigned.

    This is why the followin query returns no rows:

     select * 
     from (select *
           from some_table
           order by some_column)
     where ROWNUM <= 4 and ROWNUM > 1; 
    

    The first row of the query result does not pass ROWNUM > 1 predicate, so ROWNUM does not increment to 2. For this reason, no ROWNUM value gets greater than 1, consequently, the query returns no rows.

    Correctly defined query should look like this:

    select *
    from (select *, ROWNUM rnum
          from (select *
                from skijump_results
                order by points)
          where ROWNUM <= 4)
    where rnum > 1; 
    

    Find out more about pagination queries in my articles on Vertabelo blog:

    • Oracle ROWNUM Explained
    • Top-N and pagination queries
    0 讨论(0)
  • 2020-11-21 05:22

    In oracle

    SELECT val FROM   rownum_order_test ORDER BY val DESC FETCH FIRST 5 ROWS ONLY;
    

    VAL

        10
        10
         9
         9
         8
    

    5 rows selected.

    SQL>

    0 讨论(0)
提交回复
热议问题