Эффективный способ эмуляции LIMIT (FETCH), OFFSET в Progress OpenEdge 10.1B SQL с использованием переполнения стека

Я хочу иметь возможность использовать эквивалент MySQL LIMIT, OFFSET в Progress OpenEdge 10.1b.

Хотя команды FETCH / OFFSET доступны начиная с Progress OpenEdge 11, к сожалению, в версии 10.1B их нет, поэтому сложно создавать постраничные наборы записей (например, записи 1-10, 11-20, 21-30 и т. Д.).

ROW_NUMBER также не поддерживается 10.1b. Кажется, что это почти такая же функциональность, как была найдена в SQL Server 2000.

Если поиск выполняется всегда в порядке идентификатора первичного ключа (pkid), это может быть достигнуто с помощью «SELECT TOP 10 * ИЗ таблицы ORDER BY pkid ASC», затем путем идентификации последнего pkid и поиска следующего набора с помощью «SELECT TOP 10 *». ИЗ таблицы ГДЕ pkid> last_pkid ORDER BY pkid ASC «; это, однако, работает только при сортировке по pkid.

Моим решением было написать PHP-функцию, в которой я мог бы передать ограничение и смещение, а затем возвращать только результаты, где номер строки находился между моими определенными значениями. Я использую TOP, чтобы вернуть не больше, чем сумма лимита и смещения.

function limit_query($sql, $limit=NULL, $offset=0)
{
$out      = array();
if ($limit!=NULL) {
$sql=str_replace_first("SELECT", "SELECT TOP ".($limit+$offset), $sql);
}
$query = $db->query($sql); //$db is my DB wrapper class
$i=0;
while ($row = $this->fetch($query)) {
if ($i>=$offset) { //only add to return array if greater than offset
$out[] = $row;
}
$i++;
}
$db->free_result($query);
return $out;
}

Это хорошо работает на небольших наборах записей или на первых нескольких страницах результатов, но если общие результаты исчисляются тысячами, если вы хотите увидеть результаты на стр. 20, 100 или 300, это очень медленно и неэффективно (первая страница запрашивает только первые 10 результатов, страница 2 первых 20, но страница 100 будет запрашивать первые 1000).

Несмотря на то, что в большинстве случаев пользователь, вероятно, не рискует пройти мимо страницы 2 или 3, поэтому нехватка эффективности, возможно, не является основной проблемой, я действительно задаюсь вопросом, существует ли более эффективный способ эмуляции этой функциональности.

К сожалению, обновление до более новой версии Progress или более совершенной базы данных, такой как MySQL, не является вариантом, так как база данных предоставляется сторонним программным обеспечением.

Кто-нибудь может предложить альтернативные, более эффективные методы?

1

Решение

Я не уверен, что полностью понимаю вопрос, поэтому вот попытка дать вам ответ:
Вы, вероятно, не сможете делать то, что хотите, одним ударом по БД. Просто сортируя записи / добавляя функции, вы, вероятно, не достигнете функциональности подкачки, которую вы пытаетесь получить. Насколько я знаю, Progress не нумерует строки, если, как вы сказали, вы не сортируете по некоторому полумесяцу pkid.
Я предлагаю вам выполнить процедуру, выполняемую в бэкэнде для создания запроса с размером пакета, равным размеру страницы (в вашем случае 10), и использовать цикл для получения следующего пакета, пока вы не получите те, которые вам нужны. Посмотрите на наборы данных или используйте открытый запрос, используя MAX-ROWS.
Надеюсь, это поможет, или, по крайней мере, даст вам идею получить это. Мне на самом деле нравится ваша реализация PHP, она кажется хорошим обходным путем, а не уродливым.

1

Другие решения

Вы должны иметь возможность установить обновленную версию Progress, преобразовать ваши базы данных и перекомпилировать код для новой версии. Обычно ваша поддержка через вашего поставщика предоставит вам последнюю версию Progress (Openedge) и не будет большой проблемой. Переход с версии 10 на 11 не должен вызывать проблем при компиляции и дает вам все преимущества SQL новой версии.

Честно говоря, ваш комментарий о превосходстве MySql немного сбивает с толку, но это обсуждение другого дня. ; D

С наилучшими пожеланиями!

0

По вопросам рекламы [email protected]