#mysql #sql #oracle #offset #sql-limit
#mysql #sql #Oracle #смещение #sql-limit
Вопрос:
Первоначальные попытки получить очень простую разбивку на страницы, используя выборку n строк, а затем последующий вызов со смещением, дают перекрывающиеся записи в Oracle.
Я ожидал, что следующее даст мне два уникальных набора результатов. 1-100, а затем 101-200 результатов, которые были бы возвращены, если бы для первой строки было установлено ограничение в 200.
select * from "APPR" /* index(APPR APPR_IDX01) */ where ("APPROVER" = 'A') or ("APPROVER" > 'A') order by "APPROVER" fetch first 100 rows only ;
select * from "APPR" /* index(APPR APPR_IDX01) */ where ("APPROVER" = 'A') or ("APPROVER" > 'A') order by "APPROVER" offset 100 rows fetch next 100 rows only ;
Итак, если для утверждающего A есть 150 элементов, первые результаты должны быть:
- A, item1
- ….
- A, item100
Последующий вызов (смещение на 100), дающий
- A, item101
- …
- A, item150
- B, item1
- B, item2
- ….
- B, item201
К сожалению, второй набор содержит некоторые записи из первой партии значений. Вероятно, действительно глупая ошибка, но я не могу найти объяснение, почему это должно произойти.
—- Обновлено в результате комментариев Первичный ключ состоит из Утверждающего и нескольких других полей, которые вместе образуют составной и уникальный первичный ключ.
Код будет вызываться через ODBC и будет использоваться на серверной части Oracle и MySQL.
Комментарии:
1. Каков первичный ключ вашей таблицы?
2. Первичный ключ состоит из «утверждающего» и нескольких других столбцов, идентифицирующих утверждаемый элемент.
Ответ №1:
В Oracle, если вы делаете «order by» для столбца, содержащего одинаковые значения (например, у вас есть — ‘A’, ‘A’, ‘A’ …), порядок записей внутри значений ‘A’ будет случайным.
Пожалуйста, попробуйте изменить ваши запросы на … order by "APPROVER", rowid
…
Комментарии:
1. Random, о, предполагал, что будет некоторый «естественный» порядок, который будет сохраняться между запросами. Решение, впервые разработанное в Oracle, должно вызываться через интерфейс ODBC и также должно работать на MySQL.
2. Добавлен столбец с уникальным автоматически увеличивающимся числом, поэтому решение является универсальным для Oracle и MySQL, а также комментарии от @GMB это обеспечивает решение
Ответ №2:
Предположительно, APPROVER
это не уникальный столбец. Поскольку могут быть дубликаты, order by
клаус нестабилен, и предложение offset может генерировать дубликаты.
Простое решение — добавить больше столбцов order by
, чтобы разорвать связи. Предполагая, что (approver, item)
это уникальный набор столбцов, это будет:
select *
from appr
where approver = 'A' or approver > 'A'
order by approver, item
fetch first 100 rows only
-- then: offset 100 rows fetch next 100 rows only
Примечания:
-
нет необходимости заключать идентификаторы с заглавными буквами (имена таблиц или столбцов) в двойные кавычки: это уже используется по умолчанию в Oracle
-
круглые скобки вокруг
or
условий в этом простом случае излишни -
если
approver
всегда имеет длину в один символ, тоwhere
предложение можно упростить следующим образомwhere approver >= 'A'
-
используйте подсказки по индексу, только если вы действительно знаете, зачем вы это делаете (я не говорю, что вы этого не делаете, но я удалил его на всякий случай); в большинстве случаев база данных знает лучше
Комментарии:
1. Правильный «УТВЕРЖДАЮЩИЙ» не является уникальным. Первоначальные тесты не показали дубликатов, но при увеличении масштаба они появились. Что касается круглых скобок, то они включаются только в том случае, если код формирует набор запросов по аналогичному шаблону, некоторые из которых полагаются на скобки для обеспечения приоритета. Утверждающий — это только один символ, чтобы упростить вопрос. Отмеченные в указателе подсказки — они были добавлены только после изучения и хронометража Поясняющих планов.