Как Вы пишете запрос, куда только избранное количество строк возвращается или с самым высоким или с самым низким значением столбца.
т.е. отчет с 5 самыми высокими оплачиваемыми сотрудниками?
Лучший способ сделать это - использовать аналитические функции 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 () или одну из функций ранжирования.
Попробуйте это:
SELECT * FROM
(SELECT field1, field2 FROM fields order by field1 desc)
where rownum <= 5
Также посмотрите этот ресурс для более подробного описания того, как работает rownum.
Oracle 9i+ предоставляет аналитические функции:
Все они требуют использования предложения OVER
, что позволяет PARTITION BY
и ORDER BY
правильно настроить возвращаемое значение ROW_NUMBER
/RANK
/DENSE_RANK
.
До версии 9i единственным вариантом была работа с ROWNUM
- что, кстати, быстрее, чем использование ROW_NUMBER
(link).