我应该如何处理在PostgreSQL的“排Y中取X的”数据?(How should I handle

2019-07-19 04:52发布

我有我想能够呈现出表“中名列Y中取X的”数据。 具体地讲,我想能够呈现数据为单个行中的相对有效的方式(即,没有在表中选择的每一行)。 排名本身很简单,它是一个直ORDER BY对表中的一列。

Postgres的似乎目前在这方面的一些独特的挑战; AFAICT它没有一个RANK或ROW_NUMBER或同等功能(至少在8.3,其中我卡上的时刻)。 在邮件列表归档的规范答案似乎是创建一个临时序列,并从中选择:

test=> create temporary sequence tmp_seq;
CREATE SEQUENCE
test=*> select nextval('tmp_seq') as row_number, col1, col2 from foo;

这样看来,解决方案仍然无助的时候我想从表中选择一个单行(我想通过PK来选择它,而不是按排名)。

我可以非规范化和等级存储在一个单独的列,这使得呈现的数据琐碎的,但只是我重新定位的问题。 更新不支持ORDER BY,所以我不知道我怎么会构建一个更新查询设置行列(短期选择每行每运行一个单独的更新每一行,这似乎是太多的DB活动的触发每次行列需要更新)。

我失去了一些东西明显? 什么是正确的方式做到这一点?

编辑 :显然,我不太清楚。 我知道OFFSET /限制的,但我看不出它如何帮助解决这个问题。 我并不想选择第十届排名第一的项目,我想选择任意的项目(通过其PK,说的),然后就可以显示给用户的东西,如“排名第43位出312”

Answer 1:

如果你想排名,这样做

SELECT id,num,rank FROM (
  SELECT id,num,rank() OVER (ORDER BY num) FROM foo
) AS bar WHERE id=4

或者,如果你真的想行号,使用

SELECT id,num,row_number FROM (
  SELECT id,num,row_number() OVER (ORDER BY num) FROM foo
) AS bar WHERE id=4

当你有相同价值观的地方,他们会有所不同。 还有DENSE_RANK()如果你需要的。

这当然需要的PostgreSQL的8.4。



Answer 2:

是不是只是这样的:

SELECT  *
FROM    mytable
ORDER BY
        col1
OFFSET X LIMIT 1

或者我失去了一些东西?

更新:

如果你想显示的级别,使用:

SELECT  mi.*, values[1] AS rank, values[2] AS total
FROM    (
        SELECT  (
                SELECT  ARRAY[SUM(((mi.col1, mi.ctid) < (mo.col1, mo.ctid))::INTEGER), COUNT(*)]
                FROM    mytable mi
                ) AS values
        FROM    mytable mo
        WHERE   mo.id = @myid
        ) q


Answer 3:

ROW_NUMBER在PostgreSQL的功能是通过实施LIMIT n OFFSET skip

  • 查找概述这里 。
  • 在排名中的陷阱看到这太问题 。

编辑:既然你问了ROW_NUMBER()而不是简单的排名: row_number()被引入到PostgreSQL 8.4版本。 所以,你可能会考虑更新。 否则, 这种解决方法可能会有所帮助。



Answer 4:

上一页答复解决的问题是“选择所有的行,并得到他们的排名”,这是不是你想要的?

  • 你有一个排
  • 你想知道它的等级

做就是了 :

SELECT COUNT(*)FROM表WHERE分数> $ 1

其中$ 1是你刚才选择的行的评分(我想你想显示它,所以你可能会选择它...)。

或做:

选择一个。 ,(SELECT COUNT()FROM表B其中得分> b.score)AS秩FROM表作为其中pk = ...

但是,如果您选择的是排名最后一排,是的,你需要计算其前都排在所有行,所以您需要扫描整个表,这将是非常缓慢的。

解决方案:

SELECT COUNT(*)FROM(SELECT 1 FROM表WHERE分数> $ 1 LIMIT 30)

你会得到精确的排名为30个成绩最好,这将是快。 谁在乎失败者?

OK,如果你真的对失败者照顾,你需要做一个直方图:

假设分数可以去从0到100,你有百万失败者评分<80和10名获奖者与得分> 80。

你使多少行有一个分数X的直方图,这是一个简单的小桌子与100行。 触发器添加到您的主表更新直方图。

现在,如果你想排名具有分值x一个失败者,他的军衔是sum(HISTO)其中histo_score> X.

由于你的分数可能不是介于0十亿0和100之间,而(说),并且你需要掰过来了一下,扩大你的直方图区间,例如。 所以你只需要100个箱最大,或者使用一些日志直方图分布函数。

顺便说Postgres的确这样当你分析表中,因此,如果您设置statistics_target到100或1000的成绩,分析,然后运行:

EXPLAIN SELECT * FROM表WHERE分数> $ 1

你会得到一个不错的行数的估计。

谁需要确切的答案?



文章来源: How should I handle “ranked x out of y” data in PostgreSQL?