【问题标题】:Getting Distinct Max Values from Multiple Columns从多列中获取不同的最大值
【发布时间】:2013-04-16 19:47:35
【问题描述】:

我正在开发一个体育数据库,我想编写一个查询来返回某些类别的名称和统计值。例如,目标领先者、助攻领先者、得分领先者、+/- 领先者、罚时领先者等。我正在使用一个名为 NJDSkaters 的表格,其中包含来自特定球队的球员姓名和统计数据。查询代码如下:

SELECT CONCAT(PlayerName,' - ',Goals) AS GoalLeader, CONCAT(PlayerName,' - ',Assists)
    CONCAT(PlayerName,' - ',Points) AS PointsLeader
FROM NJDSkaters
WHERE Goals = (SELECT DISTINCT MAX(Goals) FROM NJDSkaters)
    OR Assists = (SELECT DISTINCT MAX(Assists) FROM NJDSkaters)
    OR Points = (SELECT DISTINCT MAX(Points) FROM NJDSkaters);

这是我的滑手登记表中的一个 sn-p,它将显示该查询应返回的球员:

如您所见,我想要的返回查询应该返回“Ilya Kovalchuk - 37”作为 GoalLeader,“Patrik Elias - 52”作为 AssistLeader,“Ilya Kovalchuk - 83”作为 PointsLeader。运行查询确实提供了这些结果,但包含我不想要的额外信息,如您在此处看到的:

我的问题是,我如何摆脱多余的信息?我只想要每个类别的领导者,我不想看到排名第二的球员,即使该球员在其他类别中排名第一。本质上,我要说的是,我只想要这张表中的 1 行。以前,我的代码会返回所有玩家,其中领导者位于顶部,所以这段代码离我想要的结果更近了一步,但现在我被卡住了。寻找这个问题的答案一直很有挑战性,因为通常很难找到提出问题的方法。

【问题讨论】:

    标签: mysql aggregate-functions max greatest-n-per-group


    【解决方案1】:

    你需要 PIVOT 你的数据,我会使用这样的东西:

    SELECT
      MAX(CASE WHEN NJDSkaters.Goals=mx.goals
           THEN CONCAT(PlayerName,' - ', NJDSkaters.Goals) END) GoalLeader,
      MAX(CASE WHEN NJDSkaters.Assists=mx.assists
           THEN CONCAT(PlayerName,' - ', NJDSkaters.Assists) END) AssistsLeader,
      MAX(CASE WHEN NJDSkaters.Points=mx.points
           THEN CONCAT(PlayerName,' - ', NJDSkaters.Points) END) PointsLeader
    FROM
      NJDSkaters INNER JOIN (
        SELECT MAX(Goals) goals, MAX(Assists) assists, MAX(Points) points
        FROM NJDSkaters) mx
      ON NJDSkaters.Goals=mx.goals
         OR NJDSkaters.Assists=mx.assists
         OR NJDSkaters.Points=mx.points
    

    请看小提琴here。 如果多个玩家共享相同的最大值,您可能还想使用 GROUP_CONCAT 而不是 MAX:

    SELECT
      CONCAT(GROUP_CONCAT(CASE WHEN  NJDSkaters.Goals=mx.goals
           THEN PlayerName END), ' - ', mx.goals) GoalLeader,
      CONCAT(GROUP_CONCAT(CASE WHEN NJDSkaters.Assists=mx.assists
           THEN PlayerName END), ' - ', mx.assists) AssistsLeader,
      CONCAT(GROUP_CONCAT(CASE WHEN NJDSkaters.Points=mx.points
           THEN PlayerName END), ' - ', mx.points) PointsLeader
    FROM
      NJDSkaters INNER JOIN (
        SELECT MAX(Goals) goals, MAX(Assists) assists, MAX(Points) points
        FROM NJDSkaters) mx
      ON NJDSkaters.Goals=mx.goals
         OR NJDSkaters.Assists=mx.assists
         OR NJDSkaters.Points=mx.points
    

    一点解释:

    • 子查询mx将返回最大进球数、最大助攻数和最大积分
    • 我将使用此子查询加入表 NJDSkaters 以返回具有最大进球数或最大助攻数或最大积分的所有行
    • CASE WHEN NJDSkaters.Goals=mx.goals THEN PlayerName END 将返回 PlayerName 如果该球员有最大的进球数,否则将返回 NULL。助攻和得分也是如此。
    • 使用 GROUP_CONCAT 我将 CASE WHEN 返回的所有玩家姓名连接起来。 GROUP_CONCAT 将跳过 NULL 值,并且只会连接在其类别中具有最大值的玩家
    • 使用 CONCAT,我将上面 GROUP_CONCAT 返回的字符串与每个类别的最大值连接起来。

    【讨论】:

    • 非常感谢。本学期早些时候我开始这个项目只是一个简单的数据库,我们只需要加载数据并编写简单的查询,但我想扩展和构建它并学习一些新技术。这真的很有帮助,尤其是展示了解决问题的两种方法。
    【解决方案2】:

    为什么不使用 LIMIT 1 来限制结果?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-16
      • 2020-12-24
      • 2017-08-07
      • 2020-11-03
      • 1970-01-01
      • 1970-01-01
      • 2022-01-18
      相关资源
      最近更新 更多