У меня большая проблема с оператором SQL в Oracle. Я хочу выбрать ТОП-10 записей, упорядоченных STORAGE_DB, которых нет в списке из другого оператора выбора.
Этот отлично работает для всех записей:
SELECT DISTINCT
APP_ID,
NAME,
STORAGE_GB,
HISTORY_CREATED,
TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE
FROM HISTORY WHERE
STORAGE_GB IS NOT NULL AND
APP_ID NOT IN (SELECT APP_ID
FROM HISTORY
WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009')
Но когда я добавляю
AND ROWNUM <= 10
ORDER BY STORAGE_GB DESC
Я получаю какие-то "случайные" записи. Думаю, потому что лимит имеет место до заказа.
Есть у кого-нибудь хорошее решение? Другая проблема: этот запрос очень медленный (10k + записей)
Ответы:
Вам нужно будет поместить текущий запрос в подзапрос, как показано ниже:
SELECT * FROM ( SELECT DISTINCT APP_ID, NAME, STORAGE_GB, HISTORY_CREATED, TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE FROM HISTORY WHERE STORAGE_GB IS NOT NULL AND APP_ID NOT IN (SELECT APP_ID FROM HISTORY WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') ='06.02.2009') ORDER BY STORAGE_GB DESC ) WHERE ROWNUM <= 10
Oracle применяет rownum к результату после его возврата.
Вам необходимо отфильтровать результат после того, как он был возвращен, поэтому требуется подзапрос. Вы также можете использовать функцию RANK () для получения результатов Top-N.
Для повышения производительности попробуйте использовать
NOT EXISTS
вместоNOT IN
. См. Это для получения дополнительной информации.источник
FETCH NEXT N ROWS ONLY
ответ ниже.Если вы используете Oracle 12c, используйте:
SELECT DISTINCT APP_ID, NAME, STORAGE_GB, HISTORY_CREATED, TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE FROM HISTORY WHERE STORAGE_GB IS NOT NULL AND APP_ID NOT IN (SELECT APP_ID FROM HISTORY WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') ='06.02.2009') ORDER BY STORAGE_GB DESC FETCH NEXT 10 ROWS ONLY
Дополнительная информация: http://docs.oracle.com/javadb/10.5.3.0/ref/rrefsqljoffsetfetch.html
источник
пытаться
SELECT * FROM users FETCH NEXT 10 ROWS ONLY;
источник
Что касается плохой производительности, то это может быть множество вещей, и это действительно должен быть отдельный вопрос. Однако есть одна очевидная вещь, которая может быть проблемой:
Если HISTORY_DATE действительно является столбцом даты и если у него есть индекс, то эта перезапись будет работать лучше:
Это связано с тем, что преобразование типа данных запрещает использование индекса B-Tree.
источник
Вы получаете явно случайный набор, потому что ROWNUM применяется перед ORDER BY. Итак, ваш запрос берет первые десять строк и сортирует их.0 Чтобы выбрать десять самых высоких зарплат, вы должны использовать аналитическую функцию в подзапросе, а затем отфильтровать это:
select * from (select empno, ename, sal, row_number() over(order by sal desc nulls last) rnm from emp) where rnm<=10
источник