分块查询中的全局行号

时间:2016-05-02 06:25:26

标签: sql postgresql pagination row-number postgresql-9.4

我想在行结果序列中包含一个row_number列,其中1是最新项,没有间隙。这有效:

SELECT id, row_number() over (ORDER BY id desc) AS row_number, title
FROM mytable
WHERE group_id = 10;

现在我想以1000个块的形式查询相同的数据,以便更容易记忆:

SELECT id, row_number() over (ORDER BY id desc) AS row_number, title
FROM mytable
WHERE group_id = 10 AND id >= 0 AND id < 1000
ORDER BY id ASC;

这里row_number从每个chunk的1重新开始,但我希望它就像它是全局查询的一部分一样,如第一种情况。有没有一种简单的方法可以实现这一目标?

4 个答案:

答案 0 :(得分:1)

您想查询前1000行,然后查询下一个1000行,依此类推?

通常你只需编写一个查询(你已经使用过的那个),让你的应用程序获取1000条记录,用它们做一些事情,然后获取下一个1000等等。因此,无需单独查询。

但是,编写这样的部分查询会相当容易:

select *
from
(
  SELECT id, row_number() over (ORDER BY id desc) AS rn, title
  FROM mytable
  WHERE group_id = 10
) numbered
where rn between 1 and 1000; -- <- simply change the row number range here
                             --    e.g. where rn between 1001 and 2000 for the second chunk

答案 1 :(得分:1)

你需要一个分页。试试这个

SELECT id, row_number() over (ORDER BY id desc)+0 AS row_number, title
FROM mytable
WHERE group_id = 10 AND id >= 0 AND id < 1000
ORDER BY id ASC;

下次,在WHERE子句中更改id的起始值时,请在row_number()中更改它,如下所示

SELECT id, row_number() over (ORDER BY id desc)+1000 AS row_number, title
FROM mytable
WHERE group_id = 10 AND id >= 1000 AND id < 2000
ORDER BY id ASC;

或者更好,您可以使用OFFSET和LIMIT方法进行分页 https://wiki.postgresql.org/images/3/35/Pagination_Done_the_PostgreSQL_Way.pdf

答案 2 :(得分:1)

假设:

  • id定义为PRIMARY KEY - 表示UNIQUENOT NULL。否则,您可能必须处理NULL值和/或重复(tie)。

  • 您在桌面上没有并发写入权限 - 或者您不关心拍摄快照后会发生什么。

MATERIALIZED VIEW就像展示in your answer一样,是个不错的选择。

CREATE MATERIALIZED VIEW mv_temp AS
SELECT row_number() OVER (ORDER BY id DESC) AS rn, id, title
FROM   mytable
WHERE  group_id = 10;

但索引和后续查询必须在行号rn上才能获得

  

数据块数为1000

CREATE INDEX ON mv_temp (rn);

SELECT * FROM mv_temp WHERE rn BETWEEN 1000 AND 2000;

您的实施需要一个有保证的无间隙id列 - 这将无需添加行号开头......

完成后:

DROP MATERIALIZED VIEW mv_temp;

索引会自动与表(本例中的物化视图)一起消失。

相关,更多细节:

答案 3 :(得分:0)

最后我最终这样做了:

首先,我创建一个临时的物化视图:

CREATE MATERIALIZED VIEW vw_temp AS SELECT id, row_number() over (ORDER BY id desc) AS rn, title
FROM mytable
WHERE group_id = 10;

然后我定义索引:

CREATE INDEX idx_temp ON vw_temp USING btree(id);

现在我可以非常快速地执行所有操作,并使用带编号的行:

SELECT * FROM vw_temp WHERE id BETWEEN 1000 AND 2000;

完成操作后,清理:

DROP INDEX idx_temp;
DROP MATERIALIZED VIEW vw_temp;

即使Thorsten Kettner的答案看起来最干净,但由于速度太慢,对我来说也不实用。感谢大家的贡献。对于实际使用案例中的那些人,我使用它来向Sphinx索引器提供数据。