Dilip Raj Baral
Dilip Raj Baral

Reputation: 3070

Ranking - Select corresponding column values to a MAX(column) value

I have a gameplay table with the following fields: user_id, level, clear_time

There are some N number of levels and the table keeps track of when user crosses a certain level. Now, I need to rank user based on two constraints: level and clear_time. As it is obvious, user in higher level stands ahead but when more than one user is in the same level, clear_time is what decides who is ahead i.e. the one to first clear that level stands ahead. Following is what I tried which is not working the way I want to. Level ordering works fine but clear_time is messed up.

SELECT 
    u.*,
    @rank := @rank + 1 rank
FROM
    ( SELECT
        t1.user_id user_id,
        MAX(t1.level) level,
        t1.clear_time clear_time,
        t2.username username
    FROM 
            gameplay t1
    INNER JOIN
        users t2
    ON
        ( t1.user_id = t2.id )
    GROUP BY
        user_id
    ORDER BY
        level DESC,
        clear_time ASC
    ) u
JOIN
    ( SELECT @rank := 0 ) r

I see the problem is MAX(level) doesn't get its corresponding clear_time. I can't get it done. Analyzing the results, I see the corresponding fields to MAX(t1.level) value are not selected. How do I accomplish this?

Upvotes: 3

Views: 111

Answers (1)

Greg Bowser
Greg Bowser

Reputation: 323

It sounds like gameplay has multiple entries per user_id. That is: an entry for level x and for level y both with the same user_id and you want to select the row with the highest level and the corresponding value of clear_time, but MAX will only select the maximum level in the group, and not the value of clear_time from the same row.

You can do this with an additional JOIN on gameplay. Edit: here's an example I setup:

MariaDB [test]> select * from gameplay;
+---------+---------------------+-------+
| user_id | clear_time          | level |
+---------+---------------------+-------+
|       1 | 2014-11-08 11:22:25 |     1 |
|       1 | 2014-11-09 11:22:40 |     2 |
+---------+---------------------+-------+
2 rows in set (0.00 sec)

MariaDB [test]> select * from users;
+----+----------+
| id | username |
+----+----------+
|  1 | foo      |
+----+----------+
1 row in set (0.00 sec)

The row we would want to select in this example is level=2, clear_time=2014-11-09 11:22:40. Here's my query:

MariaDB [test]> SELECT t1.user_id, t2.username, t1.level, t3.clear_time
FROM 
   (SELECT user_id, max(level) as level FROM gameplay GROUP BY user_id) as t1
INNER JOIN (users t2, gameplay t3)
ON t1.user_id=t2.id AND t3.level=t1.level AND t3.user_id=t1.user_id;

+---------+----------+-------+---------------------+

| user_id | username | level | clear_time          |
+---------+----------+-------+---------------------+
|       1 | foo      |     2 | 2014-11-09 11:22:40 |
+---------+----------+-------+---------------------+
1 row in set (0.00 sec)

Upvotes: 1

Related Questions