我想在行结果序列中包含一个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重新开始,但我希望它就像它是全局查询的一部分一样,如第一种情况。有没有一种简单的方法可以实现这一目标?
答案 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
- 表示UNIQUE
和NOT 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索引器提供数据。