2010-02-21 3 views

ответ

10

Попробуйте это:

SELECT * FROM 
    (SELECT field1, field2 FROM fields order by field1 desc) 
where rownum <= 5 

Также обратите внимание на this resource для более детального описания того, как RowNum работ.

24

Лучший способ сделать это с помощью аналитических функций, RANK() или DENSE_RANK() ...

SQL> select * from (
    2  select empno 
    3    , sal 
    4    , rank() over (order by sal desc) as rnk 
    5  from emp) 
    6 where rnk <= 5 
    7/

    EMPNO  SAL  RNK 
---------- ---------- ---------- 
     7839  5000   1 
     7788  3000   2 
     7902  3000   2 
     7566  2975   4 
     8083  2850   5 
     7698  2850   5 

6 rows selected. 

SQL> 

DENSE_RANK() сжимает пробелы, когда есть связь:

SQL> select * from (
    2  select empno 
    3    , sal 
    4    , dense_rank() over (order by sal desc) as rnk 
    5  from emp) 
    6 where rnk <= 5 
    7/

    EMPNO  SAL  RNK 
---------- ---------- ---------- 
     7839  5000   1 
     7788  3000   2 
     7902  3000   2 
     7566  2975   3 
     8083  2850   4 
     7698  2850   4 
     8070  2500   5 

7 rows selected. 

SQL> 

Какое поведение вы предпочитаете, зависит от ваших бизнес-требований.

Существует также аналитическая функция ROW_NUMBER(), которую мы можем использовать для возврата точного числа строк. Однако нам следует избегать использования решений на основе номера строки, если бизнес-логика не сможет произвольно урезать набор результатов в случае равенства. Существует разница между просить пяти самых высоких значений и первых пяти записей, отсортированных высоких значениями

Существует также не-аналитическое решение с использованием псевдо-столбца ROWNUM. Это неудобно, потому что ROWNUM применяется до предложения ORDER BY, что может привести к неожиданным результатам. Существует редко какая-либо причина использовать ROWNUM вместо ROW_NUMBER() или одну из функций ранжирования.

+0

Вы можете использовать 'QUALIFY ... <= 5' вместо того, чтобы обернуть его другим выбором. – lins314159

+0

@ lins314159 - QUALIFY не является конструкцией, которую поддерживает Oracle. – APC

+0

Я так и думал. Или ссылка на какой-то другой продукт Oracle? Http: //download.oracle.com/docs/cd/E12032_01/doc/epm.921/html_ir_studio/ir_studio-15-36.html' – lins314159

4

Oracle 9i + предоставляет аналитические функции:

Все требуют использования пункта OVER, что позволяет PARTITION BY и ORDER BY положения, чтобы правильно настроить ROW_NUMBER/RANK/Возвращаемое значение.

До 9i, единственный вариант должен был работать с ROWNUM - что, кстати, быстрее, чем с использованием ROW_NUMBER (link).

+0

Спасибо. Предложение OVER было для меня новым. +1 – road242

+0

На самом деле Oracle представила аналитические функции в 8i, но только по лицензии Enterprise Edition. В 9i они попали под лицензию Standard Edition. – APC

0

В Oracle 12c, это может быть достигнуто с помощью FETCH..FIRSTROWS..ONLY

Для того, чтобы извлечь первые 5 высокие зарплаты.

SELECT * 
     FROM EMPLOYEES 
    ORDER BY SALARY DESC 
FETCH FIRST 5 ROWS ONLY;