键集分页中不同排序顺序的实现疑问咨询
键集分页(Keyset Pagination)实现疑问解答
你已经掌握了基于created_at和id升序的键集分页基础实现,针对你的两个疑问,直接解答如下:
1. 按created_at DESC或id DESC排序的键集分页实现
当排序方向为降序时,核心逻辑是把升序里的>运算符换成<——因为降序排序下,比游标值"更小"的记录会排在更靠后的分页里。
举个按created_at DESC, id DESC排序的例子:
- 第一页查询:
SELECT * FROM event ORDER BY created_at DESC, id DESC LIMIT 3;
- 假设第一页最后一条记录的
created_at是'2024-02-09 14:21:52+00',id是'7aa20cad-3a8f-45cb-bee2-2115d4ad1c20',第二页查询:
SELECT * FROM event WHERE (created_at, id) < ('2024-02-09 14:21:52+00', '7aa20cad-3a8f-45cb-bee2-2115d4ad1c20') ORDER BY created_at DESC, id DESC LIMIT 3;
如果单独按id DESC排序,逻辑同理:用<运算符匹配游标id即可。
2. 混合排序下的筛选条件与运算符规则
当排序规则是混合方向(如name DESC, created_at ASC, id ASC)时,筛选条件需要按照排序字段的优先级和各自的排序方向组合判断,核心规则:
- 降序排序的字段:用
<运算符(找比游标值小的记录) - 升序排序的字段:用
>运算符(找比游标值大的记录) - 多字段组合时,按排序优先级依次判断:先判断第一个字段,相等时再判断第二个,以此类推。
针对你给出的排序语句,具体实现如下:
- 第一页查询:
SELECT * FROM event ORDER BY name DESC, created_at ASC, id ASC LIMIT 3;
- 假设第一页最后一条记录的
name是'发布会',created_at是'2024-02-09 14:21:52+00',id是'7aa20cad-3a8f-45cb-bee2-2115d4ad1c20',第二页查询:
SELECT * FROM event WHERE name < '发布会' OR (name = '发布会' AND created_at > '2024-02-09 14:21:52+00') OR (name = '发布会' AND created_at = '2024-02-09 14:21:52+00' AND id > '7aa20cad-3a8f-45cb-bee2-2115d4ad1c20') ORDER BY name DESC, created_at ASC, id ASC LIMIT 3;
也可以用元组比较的简化写法(部分数据库支持,比如PostgreSQL):
SELECT * FROM event WHERE (name, created_at, id) < ('发布会', '2024-02-09 14:21:52+00', '7aa20cad-3a8f-45cb-bee2-2115d4ad1c20') ORDER BY name DESC, created_at ASC, id ASC LIMIT 3;
这里的元组比较逻辑和上面的多条件OR完全一致:优先比较name(降序,所以用<),name相等时比较created_at(升序,元组比较会自动用>判断),以此类推。
运算符与排序规则的关联总结
- 升序(ASC):要获取下一页,需筛选大于游标值的记录,用
> - 降序(DESC):要获取下一页,需筛选小于游标值的记录,用
< - 混合排序:按字段排序优先级,每个字段对应自己方向的运算符,组合成完整的筛选条件。
内容的提问来源于stack exchange,提问作者Arjen
相关产品推荐
相关产品推荐

