سؤال

Having the following two tables in a MySQL Database:

USER
 - ID
 - Name

GAME1
 - ID
 - UserID
 - Score
 - Rank

This is what I need in a view:

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

I got it working without GameIDs, but I also need the IDs of the games where MaxScore and BestRank occurred.

I searched the web for some information and tried GROUP_CONCAT, HAVING, ... but I could not get the results I need.

edit

As a result of the query I except one row per user with the MaxScore and BestRank and the IDs of the games where these were reached. If a User has the same score (which is best) in more than 1 game, I only want one of these in the user row.

هل كانت مفيدة؟

المحلول 2

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

The idea is to use Subselects to find the max score and use that score to get the Game1.ID. Same idea is used for Game1.Rank.

نصائح أخرى

You could use a filtering join. The example is just for score, but you can add a second filtering join for rank.

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

Let me start by a example that doesnt solve your whole need. If you want the MaxScore for each user in each game the query looks like this:

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

The standard JOIN and the GROUP BY needs to list all the parameters that should be respected by the aggregation. (From a business logic point of view it should only list User.ID and Game1.ID, since User.Name is dependent from User.ID, but that is a technical detail and you would probably not want to redesign your database because of that.)

You could rewrite the statement above to retrieve Min(Game1.Rank) as BestRank instead. Now the question remains on how to extend that query to list both values at the same time.

You have to decide if that can be done in the same join (meaning that the highest score always is the best rank too) or if a seperate join is required (meaning that some other score than MaxScoreGameID could have the BestRank - maybe in a game you are trying to get close to 0 points?).

IF two separate joins are required, you have to join Game1 twice.

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
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

or

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

or

  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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top