Эквивалент LIMIT для DB2
Как дела LIMIT
в DB2 для iSeries?
У меня есть таблица с более чем 50 000 записей, и я хочу вернуть записи от 0 до 10 000 и записи от 10 000 до 20 000.
Я знаю в SQL ты пишешь LIMIT 0,10000
в конце запроса от 0 до 10000 и LIMIT 10000,10000
в конце запроса от 10000 до 20000
Итак, как это сделать в DB2? Какой код и синтаксис? (пример полного запроса приветствуется)
10 ответов
Разработал этот метод:
Вам нужна таблица, которая имеет уникальное значение, которое можно заказать.
Если вы хотите, чтобы строки были от 10 000 до 25 000, а в вашей таблице 40 000 строк, сначала вам нужно получить начальную точку и общее количество строк:
int start = 40000 - 10000;
int total = 25000 - 10000;
А затем передать их по коду на запрос:
SELECT * FROM
(SELECT * FROM schema.mytable
ORDER BY userId DESC fetch first {start} rows only ) AS mini
ORDER BY mini.userId ASC fetch first {total} rows only
С помощью FETCH FIRST [n] ROWS ONLY
:
SELECT LASTNAME, FIRSTNAME, EMPNO, SALARY
FROM EMP
ORDER BY SALARY DESC
FETCH FIRST 20 ROWS ONLY;
Чтобы получить диапазоны, вы должны использовать ROW_NUMBER()
(начиная с v5r4) и используйте это в WHERE
оговорка: (украдено отсюда: http://www.justskins.com/forums/db2-select-how-to-123209.html)
SELECT code, name, address
FROM (
SELECT row_number() OVER ( ORDER BY code ) AS rid, code, name, address
FROM contacts
WHERE name LIKE '%Bob%'
) AS t
WHERE t.rid BETWEEN 20 AND 25;
Поддержка OFFSET и LIMIT была недавно добавлена в DB2 для i 7.1 и 7.2. Для получения этой поддержки вам необходимы следующие уровни группы DB PTF:
- SF99702 уровень 9 для IBM i 7.2
- SF99701 уровень 38 для IBM i 7.1
Дополнительную информацию смотрите здесь: документация OFFSET и LIMIT, Wiki для DB2 for i Enhancement
Вот решение, которое я придумал:
select FIELD from TABLE where FIELD > LASTVAL order by FIELD fetch first N rows only;
Инициализируя LASTVAL в 0 (или '' для текстового поля), затем устанавливая его в качестве последнего значения в самом последнем наборе записей, это будет проходить по таблице в виде фрагментов из N записей.
Предложение позволяет ограничить количество строк, возвращаемых запросом. Предложение является расширением
SELECT
оператор, имеющий следующий синтаксис:
SELECT select_list
FROM table_name
ORDER BY sort_expression
LIMIT n [OFFSET m];
В этом синтаксисе:
- - количество возвращаемых строк.
- - количество строк, которые нужно пропустить перед возвратом строк.
Другая более короткая версия статьи выглядит следующим образом:
LIMIT m, n;
Этот синтаксис означает пропуск
m
строки и возвращение следующего
n
строки из набора результатов.
Таблица может хранить строки в неопределенном порядке. Если вы не используете предложение с предложением, возвращаемые строки также не указаны. Поэтому рекомендуется всегда использовать
ORDER BY
пункт с
LIMIT
пункт.
Смотрите Db2 LIMIT для более подробной информации.
Попробуй это
SELECT * FROM
(
SELECT T.*, ROW_NUMBER() OVER() R FROM TABLE T
)
WHERE R BETWEEN 10000 AND 20000
Решение @elcool - разумная идея, но вам нужно знать общее количество строк (которое может даже измениться во время выполнения запроса!). Поэтому я предлагаю модифицированную версию, которая, к сожалению, нуждается в 3 подзапросах вместо 2:
select * from (
select * from (
select * from MYLIB.MYTABLE
order by MYID asc
fetch first {last} rows only
) I
order by MYID desc
fetch first {length} rows only
) II
order by MYID asc
где {last}
следует заменить номером строки последней нужной мне записи и {length}
должно быть заменено на количество строк, которое мне нужно, рассчитывается как last row - first row + 1
,
Например, если я хочу строки от 10 до 25 (всего 16 строк), {last}
будет 25 и {length}
будет 25-10+1=16.
Вам также следует рассмотреть предложение OPTIMIZE FOR n ROWS. Более подробную информацию обо всем этом можно найти в документации по DB2 LUW в Руководстве по ограничению использования инструкций SELECT:
- Предложение OPTIMIZE FOR объявляет намерение получить только подмножество результата или предоставить приоритет получению только первых нескольких строк. Затем оптимизатор может выбрать планы доступа, которые минимизируют время отклика для получения первых нескольких строк.
Существует два решения для эффективного разбиения на страницы в таблице DB2:
1 - метод, использующий функцию row_number() и предложение OVER, которое было представлено в другом посте ("SELECT row_number() OVER ( ORDER BY ...)"). На некоторых больших столах я иногда замечал ухудшение производительности.
2 - техника с использованием прокручиваемого курсора. Реализация зависит от используемого языка. Эта техника кажется более надежной на больших столах.
Я представил две техники, реализованные в PHP на семинаре в следующем году. Слайд доступен по этой ссылке: http://gregphplab.com/serendipity/uploads/slides/DB2_PHP_Best_practices.pdf
Извините, но этот документ только на французском языке.
Theres эти доступные варианты:-
DB2 has several strategies to cope with this problem.
You can use the "scrollable cursor" in feature.
In this case you can open a cursor and, instead of re-issuing a query you can FETCH forward and backward.
This works great if your application can hold state since it doesn't require DB2 to rerun the query every time.
You can use the ROW_NUMBER() OLAP function to number rows and then return the subset you want.
This is ANSI SQL
You can use the ROWNUM pseudo columns which does the same as ROW_NUMBER() but is suitable if you have Oracle skills.
You can use LIMIT and OFFSET if you are more leaning to a mySQL or PostgreSQL dialect.