对分组内的行进行排名(2 列)

Posted

技术标签:

【中文标题】对分组内的行进行排名(2 列)【英文标题】:Rank rows within grouped by (2 columns) 【发布时间】:2021-03-24 06:39:54 【问题描述】:

我写了一个查询来获取这样的数据(附图),user_id 和 topic_id 被分组并计算分数的平均值。我想对每个用户的分数进行排名,因此每个用户的最高 topic_id 排名为 1。我们如何编写查询来对他们的分数进行排名,因为我需要为每个用户选择第一行。

表格是这样的 -

USER_ID        TOPIC_ID    SCORE  
------------- ------------- ------ 
 b33e3100a7be  829e4b89c318  85     
 b33e3100a7be  b19b6f2b2975  82     
 b33e3100a7be  e305c970701c  81.6   
 b33e3100a7be  6c6fac161e65  81.6   
 7379ce6bc5a9  6c6fac161e65  54.6   
 7379ce6bc5a9  e305c970701c  54.6   
 7379ce6bc5a9  b19b6f2b2975  51.6 

并希望输出看起来像这样。

 USER_ID        TOPIC_ID    SCORE  RANK
------------- ------------- ------ -----
 b33e3100a7be  829e4b89c318  85     1
 b33e3100a7be  b19b6f2b2975  82     2
 b33e3100a7be  e305c970701c  81.6   3
 b33e3100a7be  6c6fac161e65  81.6   3
 7379ce6bc5a9  6c6fac161e65  54.6   1
 7379ce6bc5a9  e305c970701c  54.6   1
 7379ce6bc5a9  b19b6f2b2975  54.6   2

enter image description here

【问题讨论】:

【参考方案1】:

您可以使用窗口函数获得所有最高分:

select t.*
from (select t.*,
             rank() over (partition by user_id order by score desc) as seqnum
      from t
     ) t
where seqnum = 1;

在这种情况下,rank() 返回所有最高的主题,如果有平局的话。 row_number() 任意返回一个。

您还可以使用相关子查询:

select t.*
from t
where t.score = (select max(t2.score)
                 from t t2
                 where t2.user_id = t.user_id
                );

请注意,这两种方法都可以合并到聚合查询中。无需保存中间结果即可获得您想要的结果。

【讨论】:

【参考方案2】:

您可以使用 distinct on 获得每次使用的最高分行:

select distinct on (user_id) t.*
from mytable t
order by user_id, score desc

如果您要显示您正在开始的数据,以及您用来生成所显示的中间结果集的查询,我们可能会进一步优化代码。您可能想为此提出一个新问题,提供适当的示例数据、所需结果和现有代码。

如果你想允许平局,那么你可以使用rank():

select *
from (
    select t.*,
        rank() over(partition by user_id order by score desc) rn
    from mytable t
) t
where rn = 1

或者,在 Postgres 13 中:

select t.*
from mytable t
order by rank() over(partition by user_id order by score desc)
fetch first 1 row with ties

【讨论】:

我已经编辑了问题、示例表和添加到其中的输出。 但是如果用户有 2 个不同的主题,并且两者的分数相同,并且它们是该用户的前两行,我需要两行而不是一行。

以上是关于对分组内的行进行排名(2 列)的主要内容,如果未能解决你的问题,请参考以下文章

我有一个带有列表的熊猫列。对包含来自同一列的至少一个公共元素的行进行分组

对具有空值和不同值的行进行分组

Pandas - 按函数和总和列分组以提取其他列总和为 0 的行

计算 20 秒间隔内的平均值并按另一列分组

如何从单个表中对多行进行分组并获取给定范围内的所有记录

在按另一个变量分组的 r 数据表中排名值