Существуют ситуации, где это полезно, но в целом этого нужно избежать. Вы могли сравнить его с GOTO или поездкой на мопеде: Вы делаете это, когда Вы должны, но Вы не говорите Вашим друзьям об этом.
Если ваша цель - найти 100 случайных строк и затем отсортировать их, тогда решение Лассе является правильным. Если, как я думаю, вы хотите, чтобы первые 100 строк были отсортированы по имени, а остальные отбросили, вы должны построить такой запрос:
SELECT *
FROM (SELECT *
FROM myTable
WHERE SIZE > 2000 ORDER BY NAME DESC)
WHERE ROWNUM <= 100
Оптимизатор поймет, что это запрос TOP-N, и сможет использовать индекс для NAME . Ему не нужно будет сортировать весь набор результатов, он просто начнет с конца индекса, прочитает его в обратном направлении и остановится после 100 строк.
Вы также можете добавить подсказку к исходному запросу, чтобы оптимизатор понял что вас интересуют только первые строки. Вероятно, это создаст аналогичный путь доступа:
SELECT /*+ FIRST_ROWS*/* FROM myTable WHERE SIZE > 2000 ORDER BY NAME DESC
Редактировать: просто добавление AND rownum <= 100
в запрос не будет работать, поскольку в Oracle rownum приписывается до сортировки: вот почему вы должны использовать подзапрос. Без подзапроса Oracle выберет 100 случайных строк и отсортирует их.
Добавьте это:
AND rownum <= 100
в предложение WHERE.
Однако это не будет делать то, что вы просите.
Если вы хотите выбрать 100 случайных строк, отсортируйте их, а затем верните, вам нужно сначала сформулировать запрос без ORDER BY, затем ограничить его до 100 строк, затем выбрать из них и отсортировать.
Это может работать, но К сожалению, у меня нет сервера Oracle для тестирования:
SELECT *
FROM (
SELECT *
FROM myTable
WHERE SIZE > 2000
AND rownum <= 100
) x
ORDER BY NAME DESC
Но обратите внимание на «случайную» часть, вы говорите: «Дайте мне 100 строк с SIZE> 2000, мне все равно, какие 100».
Это действительно то, что вы хотите?
И нет, на самом деле вы не получите случайного результата в том смысле, что он будет меняться каждый раз, когда вы запрашиваете сервер, но вы находитесь во власти оптимизатора запросов. Если статистика загрузки данных и индекса для этой таблицы со временем меняется,
Этот показывает, как выбрать первые N строк в зависимости от вашей версии Oracle.
Начиная с Oracle 9i, RANK () и Функции DENSE_RANK () могут использоваться для определить TOP N строк. Примеры:
Получите 10 лучших сотрудников на основе их зарплата
ВЫБРАТЬ ename, sal FROM (SELECT ename, sal, RANK () OVER (ЗАКАЗАТЬ sal DESC) sal_rank FROM emp) WHERE sal_rank <= 10;
Выберите сотрудников, входящих в топ-10 зарплаты
ВЫБРАТЬ ename, sal FROM (SELECT ename, sal, DENSE_RANK () OVER (ЗАКАЗАТЬ ПО sal DESC) sal_dense_rank FROM emp) WHERE sal_dense_rank <= 10;
Разница между ними объясняется здесь
Ваша проблема в том, что сортировка выполняется каждый раз при выполнении запроса.Вы можете исключить операцию сортировки, используя индекс - оптимизатор может использовать индекс для исключения операции сортировки - если отсортированный столбец объявлен как NOT NULL.
(Если столбец допускает значение NULL, это все еще возможно, либо ( a) добавление к запросу предиката NOT NULL или (b) добавление индекса на основе функций и соответствующее изменение предложения ORDER BY).