1

I have 2 tables: player_positions (records the gps coordinates of all players) and players (records data for each player).

players
player_id, player_name

player_positions
player_id, player_lat, player_lon, timestamp

I want to get last 5 positions for all players.

My first query for selecting the last locations of one player is:

SELECT * FROM player_positions WHERE player_id = 1 ORDER BY timestamp DESC LIMIT 5

But I don't know how to duplicate this query to extract all players data. I believe I have to do a select within a previous join but not sure how to write it.

Thank you.

Adrian
  • 609
  • 2
  • 11
  • 22
  • @Adrian: have a look at http://stackoverflow.com/questions/1442527/how-to-select-the-newest-four-items-per-category/1442867#1442867 – VMai May 05 '14 at 17:34
  • @VMai I think I must be doing something wrong as the moment I add in the inequality I get 0 results back... I'll keep on trying :) – Adrian May 05 '14 at 17:45
  • So can we close this as a duplicate then? – Strawberry May 05 '14 at 21:45

2 Answers2

1

Try this :

  SELECT pp.* , p.player_name 
  FROM player_positions pp 
  INNER JOIN  players p ON p.player_id = pp.player_id
  GROUP BY pp.player_id 
  ORDER BY pp.timestamp DESC LIMIT 5

EDIT:

 SELECT pp.* , p.player_name
 FROM player_positions pp
 INNER JOIN players p ON p.player_id = pp.player_id
 LEFT OUTER JOIN player_positions pp2 ON pp.player_id = pp2.player_id AND pp.timestamp < pp2.timestamp
 GROUP BY pp.player_id
 HAVING COUNT(*) < 5
 ORDER BY pp.timestamp DESC LIMIT 5
echo_Me
  • 37,078
  • 5
  • 58
  • 78
1

You can emulate the rownumber function found in other dbs like so, to solve this problem.

SELECT 
    player_id,
    player_lat,
    player_lon,
    `timestamp`
FROM 
    (SELECT 
        pp.player_id, 
        pp.player_lat,
        pp.player_lon,
        pp.`timestamp`,
        @rn := if(@prev = pp.player_id, @rn + 1,1) as rn,
        @prev:=pp.player_id

    FROM
        Player_Positions as pp
        JOIN (SELECT @Prev:= Null, @Rn := 0) as v
    ORDER BY 
        pp.player_id,
        pp.timestamp desc) as t
WHERE
    rn <= 5;

Note that if for some reason there's a tie for 5th the database will arbitrarily pick one. Since it's unlikely that a player can be in two positions for the same timestamp you should be okay.

Conrad Frix
  • 51,984
  • 12
  • 96
  • 155
  • This is brilliant, exactly what I was looking for. I haven't used user defined variables before but I think I understand how it works. Thank you! – Adrian May 06 '14 at 09:01