1

I want to get the latest highscore, per user, per game. My current query isn't working.

I have a SQL DB like the following:

player(string)  game(string)    score(int)  Date(Date)      time(Time)
jake            soccer          20          2016/02/26      10:00:00
jake            chess           50          2016/02/26      10:00:00
jake            soccer          40          2016/02/26      13:00:00
jake            chess           30          2016/02/26      13:00:00
jake            soccer          20          2016/02/26      15:00:00
jake            chess           60          2016/02/26      15:00:00
jake            soccer          80          2016/02/26      18:00:00
jake            chess           10          2016/02/26      18:00:00
mike            chess           30          2016/02/26      13:00:00
mike            soccer          20          2016/02/26      15:00:00
mike            chess           60          2016/02/26      15:00:00
mike            soccer          80          2016/02/26      18:00:00
mike            chess           10          2016/02/26      18:00:00

What I want to get out of it is:

jake            soccer          80          2016/02/26      18:00:00
jake            chess           10          2016/02/26      18:00:00
mike            soccer          80          2016/02/26      18:00:00
mike            chess           10          2016/02/26      18:00:00

I found out the Time column also has the date, so this should work. This is my current Query:

SELECT t1.*
FROM db t1
INNER JOIN (
    SELECT player, MAX(time) TS
    FROM db
    GROUP BY player
) t2 ON t2.player = t1.player and t2.TS = t1.time
ORDER BY score DESC";

EDIT: I'm getting lots of wrong rows. Basically. I'm getting them sorted by time, but not the date I now need to sort them not only by MAX(Time) but MAX(Date) as well. Or merge Date and Time in a new var

cmf
  • 435
  • 1
  • 9
  • 21

3 Answers3

1

To get the latest highscore, per user, per game, try this:

 ;WITH cte as (
 SELECT player, game, MAX(convert(datetime,cast([date] as nvarchar(10)) + ' '+ cast([time] as nvarchar(10)))) TS
 FROM db
 GROUP BY player, game)
 SELECT db.*
 FROM cte
 LEFT JOIN db ON cte.player = db.player and cte.game = db.game and cte.TS = convert(datetime,cast(db.[date] as nvarchar(10)) + ' '+ cast(db.[time] as nvarchar(10)))
 ORDER BY highscore DESC
gofr1
  • 15,741
  • 11
  • 42
  • 52
  • Thank you very much! This did it with only a couple minor bugs due to the DB being poorly built. Eventually they added a DATETIME so now I just used MAX(DT) and it works like a charm! – cmf Mar 02 '16 at 17:08
  • Great! It's right approach to keep date and time in same column! – gofr1 Mar 02 '16 at 17:33
1

Try using ROW_NUMBER()

SELECT
      t1.*
FROM (
      SELECT
            *
          , ROW_NUMBER() OVER (PARTITION BY player ORDER BY [time] DESC) AS rn
      FROM db
      ) AS t1
WHERE rn = 1
;
Paul Maxwell
  • 33,002
  • 3
  • 32
  • 51
0

Since you want not just the most recent game but also its score, this question can use the same patterns discussed here: Select first row in each GROUP BY group?

Personally I think picking the most recent time and then using that to match rows in the outer query is a little scary, since someone just might have two games at the same instant. Also it won't give you the best performance. Depending on your RDBMS, the linked question might have better approaches.

Community
  • 1
  • 1
Paul A Jungwirth
  • 23,504
  • 14
  • 74
  • 93
  • I get what you're trying to say, but in this case this dB is just a mockup. My actual dB is similar bit it's about servers, drives and disk space. The query happens once every 2 minutes so there's no same time, only same dates – cmf Feb 26 '16 at 19:12