我有关于如何使用搜索方法进行分页的问题,
在我的查询中,我需要
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
最佳答案
Seek 方法需要一个唯一的列来排序。如果你想按状态升序排序,你要做的是这样的:
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.status asc NULLS LAST,
t.id asc NULLS LAST
LIMIT $8
这将为您提供一个按状态排序的页面,如果状态相同,则按 ID 排序。您可以使用 N 列来执行此操作,请始终记住将 ID 放在最后。
为了检索下一页,您需要最后一个项目的状态/ID,查询类似于:
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
--Pagination Where Clause
AND t.status > $9
OR (t.status = $9 AND t.id > $10)
ORDER BY t.status asc NULLS LAST,
t.id asc NULLS LAST
LIMIT $8
其中 $9 是最后一项的状态,$10 是最后一项的 ID(来自上一页)。
>
更改为 <
如果您想按 DESC 排序,请在分页 where 子句上。
关于sql - 分页使用搜索方法(键集),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41404593/