Oracle TOP N упорядоченных строк - PullRequest
2 голосов
/ 28 июля 2011

Я бы хотел получить первые N строк таблицы Oracle, отсортированные по дате.

Обычный способ сделать это, и это решение возвращается для каждого вопроса, который я могу найти в SO / google.

Select *
from
(select * from
myTable 
ordered by Date desc)
where rownum < N

Это решение в моем случае неосуществимо, потому что myTable содержит огромное количество строк, которые привести к тому, что Oracle займет слишком много времени, чтобы вернуть все строки в подзапросе.

Вопрос в том, есть ли способ ограничить количество строк ORDERED, возвращаемых в подзапросе?

Ответы [ 4 ]

12 голосов
/ 28 июля 2011

Ваш вывод о том, что Oracle должен вернуть все строки в подзапросе перед фильтрацией первого N, неверен.Он начнет выборку строк из подзапроса и остановит , когда вернет N строк.

Сказав это, он может быть такимOracle должен выбрать все строки в таблице и отсортировать их, прежде чем он сможет начать их возвращать.Но если бы в столбце, который используется в предложении ORDER BY, был индекс, он мог бы этого не делать.

Oracle находится в том же положении, что и любая другая СУБД: если у вас большая таблица без индекса в столбцевы упорядочиваете, как он может знать, какие строки являются верхними N, не получив сначала все строки и не отсортировав их?

2 голосов
/ 28 июля 2011

Вопрос в том, есть ли способ ограничить количество упорядоченных строк вернулся в подзапрос?

Вот что я обычно использую для запросов типа top-n (в данном случае это разбиение на страницы):

select * from (
  select a.*, rownum r
  from (
    select *
    from your_table
    where ...
    order by ...
  ) a
  where rownum <= :upperBound
)
where r >= :lowerBound;

Я обычно использую индексированный столбец для сортировки во внутреннем запросе, а использование rownum означает, что Oracle может использовать оптимизацию count (stopkey). Таким образом, не обязательно делать полное сканирование таблицы:

create table t3 as select * from all_objects;
alter table t3 add constraint t_pk primary key(object_id);
analyze table t3 compute statistics;

delete from plan_table;
commit;
explain plan for
select * from (
  select a.*, rownum r
  from (
    select object_id, object_name
    from t3
    order by object_id
  ) a
  where rownum <= 2000
)
where r >= 1;

select operation, options, object_name, id, parent_id, position, cost, cardinality, other_tag, optimizer
from plan_table
order by id;

Вы обнаружите, что Oracle выполняет полное сканирование индекса с использованием t_pk. Также обратите внимание на использование опции stopkey.

Надеюсь, это объясняет мой ответ;)

1 голос
/ 28 июля 2011

Заказ по может стать тяжелой операцией, если у вас много данных. Посмотрите на ваш план выполнения. Если данные не в реальном времени, вы можете создать представление материала для этих видов выбора ...

0 голосов
/ 27 декабря 2018

В старых версиях ORACLE (8.0) у вас нет возможности использовать предложение ORDER BY в подзапросе. Таким образом, только для тех из нас, кто еще использует некоторые древние версии, есть еще один способ: магия оператора UNION. UNION отсортирует записи по столбцам в запросе:

Пример:

SELECT * FROM
(SELECT EMP_NO, EMP_NAME FROM EMP_TABLE
UNION
SELECT 99999999999,'' FROM DUAL)
WHERE ROWNUM<=5
where 99999999999 is bigger then all values in EMP_NO;

Или, если вы хотите выбрать ТОП 5 сотрудников с самыми высокими зарплатами: 5 1006 *

SELECT EMP_NO, EMP_NAME, 99999999999999-TMP_EMP_SAL
FROM
(SELECT 99999999999999-EMP_SAL TMP_EMP_SAL, EMP_NO, EMP_NAME 
FROM EMP_TABLE
UNION
SELECT 99999999999999,0,'' FROM DUAL)
WHERE ROWNUM<=5;

С уважением,

Вирджил Ионеску

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...