从多列获取不同的最大值

时间:2013-04-16 19:47:35

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

我正在开发一个体育数据库,我想写一个查询,它将返回某些类别的名称和统计值。例如,目标领导者,助理领导者,积分领导者,+ / - 领导者,惩罚分钟领导者等。我正在使用一个名为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);

这是我的滑板注册表中的一个片段,它会显示应该通过此查询返回的玩家:

http://imgur.com/T8gi368

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

http://imgur.com/UUxM2yA

我的问题是,我如何摆脱多余的信息?我只想要每个类别中的领导者,而且我不希望看到列出的#2玩家,即使该玩家在其他类别中排名第一。基本上,我所说的是,我想在这张表中只有一行。在此之前,我的代码会返回所有顶级领导者的代码,所以这段代码更接近我想要的结果,但现在我卡住了。寻找这个问题的答案一直很有挑战性,因为找到一种方法来解决这个问题通常很困难。

2 个答案:

答案 0 :(得分: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返回的字符串与每个类别的最大值连接起来。

答案 1 :(得分:0)

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