如何在postgres查询中排名

Wil*_*ill 26 postgresql

我正在尝试对表中的数据子集进行排名,但我认为我做错了.我找不到关于postgres的rank()功能的很多信息,也许我在找错了地方.无论哪种方式:

我想知道基于日期的属于表的集群中的id的等级.我的查询如下:

select cluster_id,feed_id,pub_date,rank 
from (select feed_id,pub_date,cluster_id,rank() 
    over (order by pub_date asc) from url_info) 
as bar where cluster_id = 9876 and feed_id = 1234;
Run Code Online (Sandbox Code Playgroud)

我在以下stackoverflow帖子后建模: postgres rank

我认为我做错了什么的原因是url_info中只有39行在cluster_id 9876中,这个查询运行了10分钟而且从未回来过.(实际上重新运行了很长一段时间并没有返回任何结果,但是在集群9876中有一行用于id 1234)我希望这会告诉我类似"id 1234对于给出的标准是第5位".会根据我的查询约束返回相对排名,对吗?

这是postgres 8.4顺便说一句.

dbe*_*hur 32

通过将rank()函数放在subselect中而不在over子句或该子选择中的任何谓词中指定PARTITION BY,您的查询要求在pub_date排序的整个url_info表上生成排名.这可能是为什么它只要排在所有url_info之上,Pg必须按pub_date排序整个表,如果表非常大,这将需要一段时间.

看来你想要为where子句选择的记录集生成一个排名,在这种情况下,你只需要消除subselect,rank函数隐含在匹配该谓词的记录集上.

select 
  cluster_id
 ,feed_id
 ,pub_date
 ,rank() over (order by pub_date asc) as rank
from url_info
where cluster_id = 9876 and feed_id = 1234;
Run Code Online (Sandbox Code Playgroud)

如果你真正想要的是群集中的排名,无论feed_id如何,你都可以在一个过滤到该群集的子选择中排名:

select ranked.*
from (
  select 
    cluster_id
   ,feed_id
   ,pub_date
   ,rank() over (order by pub_date asc) as rank
  from url_info
  where cluster_id = 9876
) as ranked
where feed_id = 1234;
Run Code Online (Sandbox Code Playgroud)

  • @isapir也许是这样,但这不是一个有力的承诺。来自[docs](https://www.postgresql.org/docs/current/static/sql-select.html#SQL-SELECT-LIST):“在更复杂的情况下,函数或类型名称**可能是* *使用,否则系统可能会使用生成的名称(例如“ column”?) (2认同)

Anv*_*esh 7

分享PostgreSQL的DENSE_RANK()的另一个例子.查找前3名学生样本查询. 从这篇博客中摘录:

创建包含示例数据的表:

CREATE TABLE tbl_Students
(
    StudID INT
    ,StudName CHARACTER VARYING
    ,TotalMark INT
);

INSERT INTO tbl_Students 
VALUES 
(1,'Anvesh',88),(2,'Neevan',78)
,(3,'Roy',90),(4,'Mahi',88)
,(5,'Maria',81),(6,'Jenny',90);
Run Code Online (Sandbox Code Playgroud)

使用DENSE_RANK(),计算学生的RANK:

;WITH cteStud AS
(
    SELECT 
        StudName
        ,Totalmark
        ,DENSE_RANK() OVER (ORDER BY TotalMark DESC) AS StudRank
    FROM tbl_Students
)
SELECT 
    StudName
    ,Totalmark
    ,StudRank
FROM cteStud 
WHERE StudRank <= 3;
Run Code Online (Sandbox Code Playgroud)

结果:

studname | totalmark | studrank
----------+-----------+----------
 Roy      |        90 |        1
 Jenny    |        90 |        1
 Anvesh   |        88 |        2
 Mahi     |        88 |        2
 Maria    |        81 |        3
(5 rows)
Run Code Online (Sandbox Code Playgroud)

  • 我认为值得指出的是 *dense_rank()* 产生没有间隙的排名(1,1,2,3,4,5,5,5,6,7,...),而 *rank()* 产生有差距的排名(1,1,3,4,5,5,7,...) (2认同)