键集/搜索分页和按搜索词过滤

时间:2018-05-15 10:07:37

标签: sql postgresql pagination

使用表格 products(id, title, price, category_id)

如何使用键集/搜索分页按标题,价格,category_id,片段过滤产品并检索第二页?一页有10个项目

https://blog.jooq.org/2016/08/10/why-most-programmers-get-pagination-wrong/

使用偏移分页的SQL将是

SELECT * FROM products
WHERE title like '%search_term%' AND price > 100 AND price < 400 AND category_id=11
ORDER BY price DESC
LIMIT 10 OFFSET 10

结果可以按此顺序

(id=23, title='Some text', price=354, category_id=11)
(id=41, title='Big text', price=333, category_id=11)
(id=43, title='big big text', price=333, category_id=11)
(id=38, title='A text', price=288, category_id=11)
(id=11, title='text', price=200, category_id=11)

1 个答案:

答案 0 :(得分:1)

用于密钥集分页的纯SQL解决方案

在谈论关键字分页时首先要理解的是,没有&#34;第二个&#34;页。只有&#34;下一页&#34;给出了一个&#34;当前页面&#34;。在您的情况下,当前页面将结束于:

(id=11, title='text', price=200, category_id=11)

因此,下一页将是具有(price, id) < (200, 11)(当前价格,ID)的页面。如果此查询生成第一页

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)

根据数据库的不同,三种不同的谓词可能会有不同的表现

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();