Чистое решение SQL для разбиения на страницы набора ключей
Первое, что нужно понять, говоря о разбиении на страницы набора ключей, это то, что не существует такой вещи, как "вторая" страница.Есть только «следующие страницы», которым дана «текущая страница».В вашем случае текущей страницей будет та, которая заканчивается:
(id=11, title='text', price=200, category_id=11)
Итак, следующая страница будет иметь страницу с (price, id) < (200, 11)
(текущая цена, идентификатор).Если в результате этого запроса будет получена ваша первая страница :
SELECT *
FROM products
-- "Ordinary predicates"
WHERE title LIKE '%search_term%'
AND price > 100 AND price < 400
AND category_id = 11
ORDER BY price DESC, id DESC
LIMIT 10
Затем этот запрос выдаст вашу следующую страницу
SELECT *
FROM products
-- "Ordinary predicates"
WHERE title LIKE '%search_term%'
AND price > 100 AND price < 400
AND category_id = 11
-- "Keyset pagination predicate"
AND (price, id) < (200, 11)
ORDER BY price DESC, id DESC
LIMIT 10
В качестве альтернативыпредикат может быть расширен до:
-- "Keyset pagination predicates"
AND (price < 200 OR price = 200 AND id < 11)
Или даже до этого:
-- "Keyset pagination predicate"
AND price <= 200
AND (price < 200 OR price = 200 AND id < 11)
В зависимости от базы данных три разных предиката могут работать по-разному
A jOOQрешение
Поскольку вы ссылаетесь на блог jOOQ, вы можете написать запрос на второй странице с помощью jOOQ:
DSL.using(configuration)
.selectFrom(PRODUCTS)
.where(PRODUCTS.TITLE.like("%search_term%")
.and(PRODUCTS.PRICE.gt(100))
.and(PRODUCTS.PRICE.lt(400))
.and(PRODUCTS.CATEGORY_ID.eq(11))
.orderBy(PRODUCTS.PRICE.desc(), PRODUCTS.ID.desc())
.seek(200, 11) // Automatic generation of keyset pagination predicates
.limit(10)
.fetch();