Я не так хорошо знаком с Oracle, как хотелось бы. У меня около 250 тыс. Записей, и я хочу отображать их по 100 на странице. В настоящее время у меня есть одна хранимая процедура, которая извлекает все четверть миллиона записей в набор данных с помощью адаптера данных, набора данных и метода dataadapter.Fill (набор данных) для результатов из хранимой процедуры. Если у меня есть целочисленные значения «Номер страницы» и «Количество записей на странице», которые я могу передать в качестве параметров, что было бы наилучшим способом вернуть только этот конкретный раздел. Скажем, если я передам 10 в качестве номера страницы и 120 в качестве количества страниц, из оператора select я получу от 1880-го до 1200-го или что-то в этом роде, моя математика в моей голове может быть отключена.
Я делаю это в .NET с C#, подумал, что это не важно, если я смогу понять это правильно на стороне sql, тогда я должен быть крутым.
Обновление: я смог использовать предложение Брайана, и оно отлично работает. Я хотел бы поработать над некоторой оптимизацией, но страницы появляются через 4–5 секунд, а не за минуту, и мой элемент управления подкачкой смог очень хорошо интегрироваться с моими новыми сохраненными процессами.


Примерно так должно работать: Из блога Франса Боумы
SELECT * FROM
(
SELECT a.*, rownum r__
FROM
(
SELECT * FROM ORDERS WHERE CustomerID LIKE 'A%'
ORDER BY OrderDate DESC, ShippingDate DESC
) a
WHERE rownum < ((pageNumber * pageSize) + 1 )
)
WHERE r__ >= (((pageNumber-1) * pageSize) + 1)
Это хорошо, но ужасно медленно для больших выборок, просто проверьте, сколько времени будет для выбора от 0 до 1000 и от 500000 до 501000 ... Я использовал такую структуру выбора, теперь я ищу обходной путь.
@ n3whous3 вы можете попробовать это - inf.unideb.hu/~gabora/pagination/results.html
Oracle говорит мне, что псевдоним «a» неоднозначен. Есть ли причина, по которой я получаю эту ошибку?
@ChrisHolmes, вы когда-нибудь получали ответ на свой вопрос. Я получаю ту же ошибку
Я не получил ответа. Мне пришлось побороться с запросом, но в конце концов он заработал. Я не могу вспомнить, что я сделал. Однако у меня все еще есть вопрос ... Дайте мне посмотреть, смогу ли я выяснить, что я сделал, и я отправлю ответ здесь.
Я задался вопросом, почему два WHERE не могут быть объединены с AND, и тут обнаружил: orafaq.com/wiki/ROWNUM
Пагинация Oracle портит мне день.
Спросите Тома о разбиении на страницы и очень, очень полезных аналитических функциях.
Это выдержка с той страницы:
select * from (
select /*+ first_rows(25) */
object_id,object_name,
row_number() over
(order by object_id) rn
from all_objects
)
where rn between :n and :m
order by rn;
На самом деле это гораздо лучшая реализация, хотя ее трудно найти в этом посте. Когда у вас много больших страниц, другой ответ также должен проходить по всем строкам с предыдущих страниц. В сложных запросах это означает, что более поздние страницы работают хуже, чем предыдущие.
@tallseth Вы правы. На этой странице его сложно найти. Добавлен отрывок.
Это правильный ответ, если вы хотите динамически изменять свой заказ.
Попробуйте следующее:
SELECT *
FROM
(SELECT FIELDA,
FIELDB,
FIELDC,
ROW_NUMBER() OVER (ORDER BY FIELDC) R
FROM TABLE_NAME
WHERE FIELDA = 10
)
WHERE R >= 10
AND R <= 15;
via [tecnicume]
В интересах полноты, для людей, ищущих более современное решение, в Оракул 12c есть некоторые новые функции, включая улучшенное разбиение по страницам и верхнюю обработку.
Пейджинг
Пейджинг выглядит так:
SELECT *
FROM user
ORDER BY first_name
OFFSET 5 ROWS FETCH NEXT 10 ROWS ONLY;
Лучшие записи N
Получение топовых записей выглядит так:
SELECT *
FROM user
ORDER BY first_name
FETCH FIRST 5 ROWS ONLY
Обратите внимание, что в обоих приведенных выше примерах запросов есть предложения ORDER BY. Новые команды соблюдают их и запускаются на отсортированных данных.
Мне не удалось найти хорошую справочную страницу Oracle для FETCH или OFFSET, но в эта страница есть отличный обзор этих новых функций.
Представление
Как отмечает @wweicker в комментариях ниже, производительность - это проблема с новым синтаксисом в 12c. У меня не было копии 18c, чтобы проверить, улучшил ли ее Oracle с тех пор.
Интересно, что мои фактические результаты были возвращены немного быстрее, когда я впервые выполнил запросы к своей таблице (более 113 миллионов строк) для нового метода:
Однако, как упоминал @wweicker, план объяснения выглядит намного хуже для нового метода:
Новый синтаксис вызвал полное сканирование индекса в моем столбце, что было полной стоимостью. Скорее всего, при ограничении неиндексированных данных все становится намного хуже.
Давайте посмотрим, включает ли один неиндексированный столбец в предыдущий набор данных:
Резюме: используйте с осторожностью, пока Oracle не улучшит эту обработку. Если у вас есть индекс для работы, возможно, вам удастся использовать новый метод.
Надеюсь, у меня скоро будет копия 18c, с которой можно будет поиграть, и я смогу обновить
Это отличный ответ для пользователей 12c
Синтаксис чище, но производительность хуже (dba-presents.com/index.php/databases/oracle/…)
Полезно знать, спасибо @wweicker. Надеюсь, Oracle скоро исправит производительность; хотя, зная Oracle, это может быть далекой надеждой!
Синтаксис новый и преобразован в обычные вызовы ROW_NUMBER / RANK. Связанные Как ограничить количество строк, возвращаемых запросом Oracle после заказа?
@JoelC изменилось ли ваше мнение?
похоже, что Oracle позаботилась о проблемах с производительностью. смотрите здесь - blogs.oracle.com/optimizer/fetch-first-rows-just-got-faster
Сразу хочу подытожить ответы и комментарии. Есть несколько способов разбивки на страницы.
До oracle 12c не было функциональности OFFSET / FETCH, поэтому взгляните на белая бумага, как предлагал @jasonk. Это самая полная статья о различных методах, которую я нашел, с подробным объяснением преимуществ и недостатков. Чтобы скопировать их сюда, потребуется много времени, поэтому я не буду этого делать.
Также есть хорошая статья от создателей jooq, объясняющая некоторые общие предостережения при разбивке на страницы Oracle и других баз данных. сообщение в блоге jooq
Хорошие новости, начиная с oracle 12c у нас появилась новая функциональность OFFSET / FETCH. Новые возможности OracleMagazine 12c. Пожалуйста, обратитесь к разделу «Топ-N запросов и разбивки на страницы».
Вы можете проверить свою версию оракула, выполнив следующее заявление
SELECT * FROM V$VERSION
В своем проекте я использовал Oracle 12c и Java. Код подкачки выглядит так:
public public List<Map<String, Object>> getAllProductOfferWithPagination(int pageNo, int pageElementSize, Long productOfferId, String productOfferName) {
try {
if (pageNo==1){
//do nothing
} else{
pageNo=(pageNo-1)*pageElementSize+1;
}
System.out.println("algo pageNo: " + pageNo +" pageElementSize: "+ pageElementSize+" productOfferId: "+ productOfferId+" productOfferName: "+ productOfferName);
String sql = "SELECT * FROM ( SELECT * FROM product_offer po WHERE po.deleted=0 AND (po.product_offer_id=? OR po.product_offer_name LIKE ? )" +
" ORDER BY po.PRODUCT_OFFER_ID asc) foo OFFSET ? ROWS FETCH NEXT ? ROWS ONLY ";
return jdbcTemplate.queryForList(sql,new Object[] {productOfferId,"%"+productOfferName+"%",pageNo-1, pageElementSize});
} catch (Exception e) {
System.out.println(e);
e.printStackTrace();
return null;
}
Да, это «встроенный» столбец, который поддерживает Oracle, он всегда начинается с 1 и увеличивается для каждой строки. Итак, в этом фрагменте кода, если у вас 1000 строк, применяется порядок сортировки, а затем каждой строке назначается rownum. Внешний выбор (ы) использует эти номера строк для поиска «страницы», которую вы ищете, в зависимости от размера вашей страницы.