Sql 分页:找出项目所在的页面(给定主键和排序顺序)
假设我这样做分页:Sql 分页:找出项目所在的页面(给定主键和排序顺序),sql,postgresql,pagination,Sql,Postgresql,Pagination,假设我这样做分页: SELECT article_id, article_content FROM articles ORDER BY article_rating OFFSET (page - 1) * items_per_page LIMIT items_per_page; SELECT article_id, article_content FROM articles ORDER BY article_rating, arti
SELECT article_id,
article_content
FROM articles
ORDER BY article_rating
OFFSET (page - 1) * items_per_page
LIMIT items_per_page;
SELECT article_id,
article_content
FROM articles
ORDER BY article_rating,
article_id
OFFSET (page - 1) * items_per_page
LIMIT items_per_page;
Select ceiling(rowNumber/items_per_page)
from (
SELECT article_id
, article_content
, row_number() over (order by article_rating, article_id)
as rowNumber
FROM articles
where article_rating <= (select article_rating
from articles
where article_id = 'xxxx' )
ORDER BY article_rating,
article_id
) x
where article_id = 'xxxx'
我有一个关于文章等级的索引,文章id
我的问题是:如果我想知道一篇文章在哪一页,最有效的方法是什么
a知道这篇文章吗
b知道排序是按物品的顺序排列的吗
它需要高效,因为我将经常进行这种类型的查询
如果它不仅能说出页码,还能说出该页上的所有文章,那就更好了
因此,例如,如果所有文章都按评级排序,并且每十篇文章都放在不同的页面上,那么我想知道ID为839的文章放在哪一页上
我正在使用PostgreSQL 8.4,如有必要,我愿意更新
谢谢大家!
编辑:
正如下面的评论所指出的,我的查询应该是这样的:
SELECT article_id,
article_content
FROM articles
ORDER BY article_rating
OFFSET (page - 1) * items_per_page
LIMIT items_per_page;
SELECT article_id,
article_content
FROM articles
ORDER BY article_rating,
article_id
OFFSET (page - 1) * items_per_page
LIMIT items_per_page;
Select ceiling(rowNumber/items_per_page)
from (
SELECT article_id
, article_content
, row_number() over (order by article_rating, article_id)
as rowNumber
FROM articles
where article_rating <= (select article_rating
from articles
where article_id = 'xxxx' )
ORDER BY article_rating,
article_id
) x
where article_id = 'xxxx'
请参见下面的第二个查询,它比第一个查询好得多
假设Postgres 9.0或更高版本,您必须使用窗口函数在每个项目上获取行号。然后将特定文章的行号除以每页的项目数,然后四舍五入得到页码。唯一可以提高效率的方法是,至少不要查询问题文章后面的文章。你会得到这样的结果:
SELECT article_id,
article_content
FROM articles
ORDER BY article_rating
OFFSET (page - 1) * items_per_page
LIMIT items_per_page;
SELECT article_id,
article_content
FROM articles
ORDER BY article_rating,
article_id
OFFSET (page - 1) * items_per_page
LIMIT items_per_page;
Select ceiling(rowNumber/items_per_page)
from (
SELECT article_id
, article_content
, row_number() over (order by article_rating, article_id)
as rowNumber
FROM articles
where article_rating <= (select article_rating
from articles
where article_id = 'xxxx' )
ORDER BY article_rating,
article_id
) x
where article_id = 'xxxx'
编辑以回应评论中的问题。是的,我刚刚意识到有更好的方法。通过运行count*,我们只遍历索引
Select ceiling(count(*)/items_per_page)
FROM articles
where article_rating < (select article_rating
from articles
where article_id = 'xxxx' )
or ( article_rating = (select article_rating
from articles
where article_id = 'xxxx' )
and article_id <= 'xxxx')
通常我们不喜欢WHERE子句中的OR子句,因为它们会降低性能,但这一条应该是相当安全的,因为如果文章评级被索引,每个子句都应该是可优化的。如果有多个项目具有相同的文章评级,这可能会特别棘手-它可能会出现在许多不同的页面上。@Damien_不信者:你是对的,我应该按文章评级排序,如果两个或更多的文章具有相同的评级,文章将获得确定的顺序。非常感谢您的快速回复。我担心会归结为这样的事情。页码越高,查询速度可能会越慢,不是吗?有什么我可以做的,不让执行时间取决于文章的页面吗?谢谢你的编辑。不幸的是,我在接下来的几天里无法访问我的PostgreSQL机器,所以我现在无法测试它的实际运行情况。但是我想如果它只需要遍历索引,即使页码很高,它也应该非常快;我对这个假设正确吗?