返回每个组的最大值,但是当存在平局时,在 MySQL 中返回一个具有较低 id 的值

Posted

技术标签:

【中文标题】返回每个组的最大值,但是当存在平局时,在 MySQL 中返回一个具有较低 id 的值【英文标题】:return max value for each group but when there is a tie, return one with lower id in MySQL 【发布时间】:2021-03-17 18:21:26 【问题描述】:

我正在使用 mysql 8.0

我的桌子是这样的:

group   user_id    score
  A        1        33
  B        2        22
  A        3        22
  B        4        22

我希望它返回

group   user_id score
  A        1     33
  B        2     22

请注意,即使 B 组的分数相同,user_id=2 也是最终获胜者,因为他/她的 user_id 较低

如何从下面的查询中改进...?

SELECT group, user_id, max(score)
  from table

提前致谢!

【问题讨论】:

请注意,GROUP 是 MySQL 中的保留字,因此不适合作为表/列标识符。 啊是的,这只是一个示例组列实际上是一个不同的名称,但感谢您指出! 【参考方案1】:

@Ambleu 您使用MAX() 是在正确的轨道上,但要做到这一点,除了MIN() 之外,您还需要使用它,并且还需要使用子查询来获取MAX(score),如下所示:

SELECT `mt`.`group`,
    MIN(`mt`.`user_id`) AS `user_id`,
    `mt`.`score`
FROM `myTable` AS `mt`
JOIN (SELECT `group`,
        MAX(`score`) AS `score`
      FROM `myTable`
      GROUP BY `group`) AS `der` ON `der`.`group` = `mt`.`group`
        AND `der`.`score` = `mt`.`score`
GROUP BY `mt`.`group`, `mt`.`score`

Here are your tables and the solution query mocked up on db-fiddle.

如果这不能满足您的需求,请告诉我,我会尽力提供进一步帮助。

【讨论】:

太棒了!谢谢!【参考方案2】:

在 MySQL 8.0 中,我会推荐窗口函数:

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

或者,您可以使用相关子查询进行过滤:

select t.*
from mytable t
where user_id = (
    select t1.user_id
    from mytable t1
    where t1.grp = t.grp
    order by t1.score desc, t1.user_id limit 1
)

第二个查询将利用(grp, score desc, user_id) 上的索引。

旁注:group 是语言关键字,因此不适合作为列名。我在查询中将其重命名为grp

【讨论】:

提及窗口函数的好主意,赞成

以上是关于返回每个组的最大值,但是当存在平局时,在 MySQL 中返回一个具有较低 id 的值的主要内容,如果未能解决你的问题,请参考以下文章

计算每个组的排名,但计算平局为1

当存在平局时如何总结数据集中的前 3 个最高值

返回 Netezza SQL 中每个组的最大值日期

每个组的本地最大值的 SQL 排序结果

解决 mySQL 中每个组的最大得分球员

当表很大时找到每个组的最大记录时如何优化sql?