【问题标题】:Keyset/seek pagination and filter by search termKeyset/seek 分页和按搜索词过滤
【发布时间】:2018-10-25 03:05:14
【问题描述】:

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

如何按标题、价格、category_id、pieces 过滤产品并使用 keyset/seek 分页检索第二页?一个页面有 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)

【问题讨论】:

    标签: sql postgresql pagination


    【解决方案1】:

    keyset 分页的纯 SQL 解决方案

    在谈论键集分页时,首先要了解的是,没有“第二”页这样的东西。给定“当前页面”,只有“下一页”。在您的情况下,当前页面将结束于:

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

    因此,下一页将是具有(price, id) &lt; (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();
    

    【讨论】:

    • 谢谢。如何理解(price, id) &lt; (200, 11)这个谓词?
    • @tewumat:我已经预见到你的问题并在我的回答中解释了它,我邀请你重新阅读。当你遇到“expanded”这个词时,把它读作expanded
    猜你喜欢
    • 2017-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-04
    • 1970-01-01
    • 2018-08-17
    • 2023-03-06
    • 2023-04-07
    相关资源
    最近更新 更多