У меня большая проблема с SQL-выражением в Oracle. Я хочу выбрать TOP 10 записей, заказанных STORAGE_DB, которые не входят в список из другого оператора select.
Этот файл отлично работает для всех записей:
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
. Подробнее см. .
Что касается плохой работы, то существует множество вещей, которые могут быть, и это действительно должен быть отдельный вопрос. Однако есть одна очевидная вещь, которая может быть проблемой:
WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009')
Если HISTORY_DATE действительно является столбцом даты, и если у него есть индекс, то этот переписать будет работать лучше:
WHERE HISTORY_DATE = TO_DATE ('06.02.2009', 'DD.MM.YYYY')
Это связано с тем, что преобразование типа данных отключает использование индекса B-Tree.
Если вы используете Oracle 12c, используйте:
FETCH NEXT N ROWS ONLY
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
Вы получаете явно произвольный набор, потому что ROWNUM применяется до ORDER BY. Таким образом, ваш запрос занимает первые десять строк и сортирует их. Чтобы выбрать первую десятку зарплат, вы должны использовать аналитическую функцию в подзапросе, а затем отфильтровать это:
select * from
(select empno,
ename,
sal,
row_number() over(order by sal desc nulls last) rnm
from emp)
where rnm<=10
попробовать SELECT * FROM пользователей FETCH NEXT 10 ROWS ONLY;
Вы можете просто использовать TOP Clause
ВЫБРАТЬ ТОП 10 * ОТ ТАБЛИЦЫ
Или
SELECT column_name (s) FROM table_name WHERE ROWNUM <= number;