【问题标题】:MySQL GROUP BY ignores the ORDER BY and always returns the 1st rowMySQL GROUP BY 忽略 ORDER BY 并始终返回第一行
【发布时间】:2021-07-14 14:01:59
【问题描述】:

我已经阅读了大量类似的问题,但没有人回答我的问题。

我想选择整行,其中包含每个组的其中一列的最大值。

SELECT * FROM (
    
    SELECT t1.* FROM `t1` JOIN `t2` ON t2.id=t1.raceId ORDER BY t1.points DESC

) AS new GROUP BY new.athleteId ORDER BY new.points DESC

这很有效,我为每个运动员提供了一行,但它显示的行只是数据库中最早的行,而不是最高分的行。

单独的子查询以正确的顺序显示所有行,但是当我尝试对它们进行分组时,它仍然取最早的行并忽略排序。

我可以检索每个分组的最大分数,但其余的行信息仍然来自最早的条目。

【问题讨论】:

  • 你的表中点的数据类型是什么?与查询共享示例数据和表结构,并共享预期输出。此外,不需要在内部查询中排序。
  • MySQL 5.7.5 及更高版本还允许在启用 ONLY_FULL_GROUP_BY SQL 模式时未在 GROUP BY 子句中命名的非聚合列,前提是该列仅限于单个值 dev.mysql.com/doc/refman/5.7/en/group-by-handling.html。我不确定我是否看到您将限制为单个值,因此 group by 是“混淆的”但是,它应该是一个错误;所以我怀疑您没有启用 ONLY_FULL GROUP BY 或使用的是允许此操作的先前版本。

标签: mysql group-by


【解决方案1】:

GROUP BY 子句旨在与聚合函数一起使用。

您想通过GROUP BY 实现什么目标?

【讨论】:

  • 因为我的查询从一组特定的比赛中提取了所有运动员的结果,2 次或更多。所以在数据集中,我可能对每个运动员有超过 1 个结果。但我只想包括他们得分最高的每个运动员的行。所以在最终的数据集中,运动员有 1 个唯一的行。这就是我尝试按运动员分组的原因
【解决方案2】:

也许是实现你所追求的一种方式..

作为一般经验法则;明智的做法是使用“GROUP BY”来定义要使用的聚合函数。 MySQL 允许您在没有定义 aggerate 函数的情况下进行分组,但我发现这非常令人困惑,因为我非常具体地要聚合的内容。也许是因为我在 SQL Server 和 oracle 方面的背景;不允许您以这种方式使用组...

基本上获取每个运动员的最高分,然后加入您的整个数据集以限制该运动员和积分。如果您还需要按种族划分运动员,可能需要按种族进行,我不确定您是否希望按种族获得最高运动员积分,但基于分组/顺序,我猜不是。

SELECT t1.*, t2.*
FROM (SELECT athlete, max(t1.points) 
      FROM `t1` 
      INNER JOIN `t2` ON t2.id=t1.raceId
      GROUP BY athlete) new
INNER JOIN `t1` on T1.athletID = new.athletID
               and t1.points = new.points
INNER JOIN JOIN `t2` ON t2.id=t1.raceId
ORDER BY new.points DESC

另一种取决于 mySQL 版本的方法是使用分析函数和聚合函数...但没有版本号,我不会详细说明。

【讨论】:

  • 感谢您的回答。只是通读 SQL,我认为这种方法会奏效。我没想过要那样做。我稍后会测试它并回复你。同时,您能否解释一下为什么使用我的 SQL 可以获得所需的行,但无法指定对分组进行排序的方式。为什么不管我做什么,它都会选择数据库中的第一行条目。我确信必须有一种不使用子查询的简单方法来做到这一点。
  • 我几乎用过这种方法。稍微调整了一下,然后遇到了一个问题,即得分为 0 的人有多个行(如果人们得分相同,也会发生同样的情况)。我只是通过再次分组来解决这个问题,所以每个运动员只有 1 行。我仍然无法相信没有一种简单的方法可以做到这一点,即按排序组
  • Order by 在您的内联视图的上下文中没有任何意义,因为您没有做一个 top 或 order by 会对结果集产生影响的事情。所以 order by 不会添加任何价值。外部顺序最终成为先例。如果您提供示例数据集以及预期结果,我们或许能够解决重复问题或找到更优雅的方法来解决此问题。
  • 还定义您使用的 mySQL 版本。如果支持分析函数,例如“over partition by”和公用表表达式,我们可以根据所需的顺序分配行号。这可以在早期版本中完成;只是没那么简单/优雅。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-01
相关资源
最近更新 更多