【发布时间】:2017-05-15 05:57:12
【问题描述】:
我对如何使用 seek 方法进行分页有疑问,
在我的查询中,我需要
1.对多列排序
2.某些列不是唯一的
例如,如果数据如下所示并查询select * from ... order by name asc, status asc ....(other column), id asc并获取8 1 3 10 2 5 6 7 9 4
现在,如果我想分页每次选择 2 行,
第一页与上述查询相同,只需添加限制 2 select * from ... order by name asc, status asc ....(other column), id asc。
如何选择下一页?
如果只是 id 列,我知道它是检查顺序,如果 asc 则发现 id 大于先前结果中的最大 id。
但是如果列是多个并且有些不是唯一值,如何解决?
id | name | status | ...
1 b 0
2 b 0
3 b 0
4 j 0
5 f 0
6 g 0
7 h 0
8 a 0
9 i 0
10 b 0
问 1。
// example table
CREATE TABLE IF NOT EXISTS "table"(
"id" SERIAL NOT NULL,
"create_date" timestamp without time zone NOT NULL,
"create_by_user_id" integer NOT NULL,
"last_modified_date" timestamp without time zone DEFAULT NULL,
"last_modified_by_user_id" integer DEFAULT NULL,
"url_id" varchar(50) NOT NULL,
"status" integer NOT NULL,
"rank" integer NOT NULL,
"name" varchar DEFAULT NULL,
"name_slug" varchar DEFAULT NULL,
"description" varchar DEFAULT NULL,
"start_date" date NOT NULL,
"end_date" date NOT NULL,
PRIMARY KEY ("id"),
UNIQUE ("url_id"),
FOREIGN KEY ("create_by_user_id") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
// select first page
SELECT * FROM table
ORDER BY name ASC NULLS LAST
, status ASC NULLS LAST
, rank DESC NULLS LAST
, id ASC
LIMIT 2;
// select next page How do I know use <, >, <=, >= in below ?
SELECT * FROM table
WHERE name ?? operator prev_end_name
AND status ?? prev_end_status
AND rank ?? prev_end_rank
AND id ?? prev_end_id
ORDER BY name ASC NULLS LAST
, status ASC NULLS LAST
, rank DESC NULLS LAST
, id ASC
LIMIT 2;
我做了一些研究,我在网上找到的所有相关帖子都显示相同的东西使用以前的 id ...但在现实生活中如何使用不同的和多列排序?像 instagram api 也使用以前的 id 但如何按许多其他列进行排序和排序..
http://use-the-index-luke.com/sql/partial-results/fetch-next-page
http://leopard.in.ua/2014/10/11/postgresql-paginattion
https://blog.jooq.org/2013/10/26/faster-sql-paging-with-jooq-using-the-seek-method/
https://www.citusdata.com/blog/2016/03/30/five-ways-to-paginate/
https://www.reddit.com/r/programming/comments/2crwyg/we_need_tool_support_for_keyset_pagination/
请不要提供使用页码设置偏移限制来分页的方式,这不是我要找的。
问题 2.
我正在使用 node.js,
不使用任何查询生成器 orm 库,
我的模型的一部分构建如下查询,
因此,如果需要对多列进行排序,则很难添加 seek 方法。
想知道人们通常如何在现实生活中的大站点 nodejs + postgres 应用程序中做到这一点,
任何建议将不胜感激!
if (typeof request.data.query.pagination_type != 'undefined') {
if (request.data.query.pagination_type == 'seek') {
if (typeof request.data.query.sort_order_list != 'undefined') {
for (var i = 0; i < request.data.query.sort_order_list.length; i++) {
if (request.data.query.sort_order_list[i].sort == 'name') {
if (typeof request.data.query.prev_end_name != 'undefined') {
if (!start) { dbQuery += ' AND'; } else { dbQuery += ' WHERE'; }
if (start) { start = false; }
if (request.data.query.sort_order_list[i].order == 'asc') {
dbQuery += ` ee.name < $` + paramsIndex;
} else if (request.data.query.sort_order_list[i].order == 'desc') {
dbQuery += ` ee.name > $` + paramsIndex;
}
paramsIndex++;
dbParams.push(request.data.query.prev_end_name);
}
} else if (request.data.query.sort_order_list[i].sort == 'start_date') {
...
查询输出类似
SELECT t.*
FROM task t WHERE
t.status = $1
AND t.rank >= $2
AND t.end_date >= $3
AND t.rank < $4
AND t.end_date < $5
AND t.name < $6
AND t.start_date > $7
ORDER BY t.rank asc NULLS LAST,
t.end_date asc NULLS LAST,
t.name asc NULLS LAST,
t.start_date desc NULLS LAST LIMIT $8
【问题讨论】:
-
常规的
OFFSET+LIMIT方法有什么问题?这是通常的做法。 -
没有错,我现在用offset + limit,提供两个参数输入,page或者previous id(如果输入previous id使用row_number查找offset)。我只是想尝试学习seek方法(keyset)
标签: sql node.js database postgresql pagination