查询以获取行的标识符和聚合函数值

时间:2014-02-12 10:20:17

标签: mysql sql group-by aggregate greatest-n-per-group

在MySQL数据库中包含以下两个表:

USER
 - ID
 - Name

GAME1
 - ID
 - UserID
 - Score
 - Rank

这是我在视图中所需要的:

 - User.ID
 - User.Name
 - Game1.ID as MaxScoreGameID
 - Max(Game1.Score) as MaxScore
 - Game1.ID as BestRankGameID
 - Min(Game1.Rank) as BestRank

我在没有GameID的情况下工作,但我还需要发生MaxScoreBestRank的游戏的ID。

我在网上搜索了一些信息,并尝试GROUP_CONCATHAVING,...但我无法得到我需要的结果。

修改

作为查询的结果,我除了每个用户使用MaxScoreBestRank的一行以及达到这些内容的游戏的ID。 如果一个用户在一个以上的游戏中得分相同(最好),我只想在用户行中使用其中一个。

4 个答案:

答案 0 :(得分:1)

您可以使用过滤联接。该示例仅用于评分,但您可以为排名添加第二个过滤联接。

select  u.name
,       g1.ID as MaxScoreGameID
,       g1.Score as MaxScore
from    User u
join    (
        select  UserID
        ,       max(Score) as maxScore
        from    Game1
        group by
                UserID
        ) as MaxScorePerUser
on      MaxScorePerUser.UserID = u.ID
join    Game1 g1
on      u.ID = g1.UserID
        and MaxScorePerUser.MaxScore = g1.Score

答案 1 :(得分:0)

SELECT u.ID
     , u.Name
     , (SELECT sub.ID from Game1 as sub where sub.UserID = u.ID ORDER BY sub.Score desc LIMIT 1) as MaxScoreGameID
     , Max(Game1.Score) as MaxScore
     , (SELECT sub2.ID from Game1 as sub2 where sub2.UserID = u.ID ORDER BY Rank asc LIMIT 1) as BestRankGameID
     , Min(Game1.Rank) as BestRank
FROM [User] u
JOIN Game1 on Game1.UserID = u.ID GROUP BY u.ID, u.Name

这个想法是使用Subselects找到最大分数并使用该分数来获得Game1.ID。同样的想法用于Game1.Rank。

答案 2 :(得分:0)

select u.id, u.name, g1.Score as MaxScore, g2.Rank as BestRank,
from user u
left outer join
 (select  g11. UserID, max(g11.Score) as Score from GAME1 as g11 group by  g12.UserID 
 ) g1 on u.id=g1.UserID
 left outer join
 (select  g12.UserID, max(g12.Rank) as Rank  from GAME1 as g12 group by  g12.UserID 
 ) g2 on u.id=g2.UserID

select u.id, u.name, g3.id, g1.Score as MaxScore, g3.id, g2.Rank as BestRank,
from user u
left outer join
 (select  g11. UserID, max(g11.Score) as Score from GAME1 as g11 group by  g12.UserID 
 ) g1 on u.id=g1.UserID
 left outer join
 (select  g12.UserID, max(g12.Rank) as Rank  from GAME1 as g12 group by  g12.UserID 
 ) g2 on u.id=g2.UserID
 left outer join GAME1 g3 on (g1.Score=g3.Score or g2.Rank=g3.Rank) and u.id=g3.UserID

  select u.id, u.name, g3.id, g1.Score as MaxScore, g4.id, g2.Rank as BestRank,
    from user u
    left outer join
     (select  g11. UserID, max(g11.Score) as Score from GAME1 as g11 group by  g12.UserID 
     ) g1 on u.id=g1.UserID
     left outer join
     (select  g12.UserID, max(g12.Rank) as Rank  from GAME1 as g12 group by  g12.UserID 
     ) g2 on u.id=g2.UserID
     left outer join GAME1 g3 on g1.Score=g3.Score and u.id=g3.UserID
      left outer join GAME1 g4 on  g2.Rank=g4.Rank and u.id=g4.UserID

答案 3 :(得分:0)

让我先举一个不能解决你全部需求的例子。如果您想要每个游戏中每个用户的MaxScore,则查询如下所示:

SELECT 
    User.ID,
    User.Name,
    Game1.ID as MaxScoreGameID,
    Max(Game1.Score) as MaxScore,
FROM
    User
JOIN
    Game1
ON
    Game1.UserID = User.ID
GROUP BY
    User.ID, User.Name, Game1.ID

标准JOINGROUP BY需要列出聚合应该遵守的所有参数。 (从业务逻辑的角度来看,它应该只列出User.ID和Game1.ID,因为User.Name依赖于User.ID,但这是一个技术细节,你可能不希望重新设计你的数据库,因为那样。)

您可以重写上述语句以取代Min(Game1.Rank) as BestRank。现在的问题仍然是如何扩展该查询以同时列出两个值。

你必须决定是否可以在同一个连接中完成(意味着最高分也是最佳排名),或者是否需要单独连接(意味着除了MaxScoreGameID之外的其他分数可能具有BestRank - 也许在游戏中你试图接近0分?)。

如果需要两个单独的连接,则必须加入Game1两次。

SELECT 
    User.ID,
    User.Name,
    g1max.ID as MaxScoreGameID,
    Max(g1max.Score) as MaxScore,
    g1min.ID as BestRankGameID,
    Min(g1min.Rank) as BestRank,
FROM
    User
JOIN
    Game1 g1max
ON
    g1max.UserID = User.ID
JOIN
    Game1 g1min
ON
    g1min.UserID = User.ID
GROUP BY
    User.ID, User.Name, g1max.ID, g1min.ID