分页使用搜索方法(键集)

时间:2016-12-31 01:17:56

标签: sql node.js database postgresql pagination

我有关于如何进行分页使用搜索方法的问题,
在我的查询中我需要
1.sort and order multiple column
2.some列不唯一

例如,如果数据如下所示,请执行查询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库,
我的模型的一部分构建如下的查询,
因此,如果需要对许多列进行订购,那么添加搜索方法是如此困难 想知道人们通常如何在现实生活中大网站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

2 个答案:

答案 0 :(得分:0)

Seek 方法需要一个唯一的列来排序。如果你想按状态 asc 排序,你需要做的是这样的:

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 子句上的 > 更改为 <

答案 1 :(得分:-2)

假设您的ID是数字完整集(没有删除的行),您可以按Id订购子查询,将WHERE子句限制为页码(0表示第一页返回0到10,1表返回11到20等)

    SELECT TOP 10 * FROM
        ( SELECT  *
        FROM Table
        WHERE Id > 5 * @PageNumber
        ORDER BY Id )