Search code examples
mysqlsqlunionleaderboardsql-limit

Ensure that the correct number of rows are returned from a MySQL query


I have a (game) leaderboard table which contains a rank which is updated by another query. It is centered around the ID - when I query the table I ideally want to get back N records. So I have done a UNION on the records both with the limit N/2 like so:

(SELECT * FROM test1 t WHERE t.rank > (SELECT rank FROM test1 t2 WHERE id=ID)+0 ORDER BY rank LIMIT 0, N/2)
UNION ALL
(SELECT * FROM test1 t WHERE t.rank <= (SELECT rank FROM test1 t2 WHERE id=ID)+0 ORDER BY rank desc LIMIT 0, N/2) ORDER BY rank

Although this does not quite work when at the top of the leaderboard, it will only return the lower N/2. Is there a way to ensure that it will always return the N records? I did think that you could purposefully get more records than required and then trim the records off which you don't need. Although I do not know how to do this with a query!

Any help appreciated :)


Solution

  • You can do this with a clever use of order by and limit:

    SELECT t.*
    FROM test1 t cross join
         (SELECT rank FROM test1 t2 WHERE id = @ID) as theone
    ORDER BY ABS(theone.rank - t.rank)
    LIMIT N;
    

    You probably then want these back in rank order:

    SELECT t.*
    FROM (SELECT t.*
          FROM test1 t cross join
               (SELECT rank FROM test1 t2 WHERE id = @ID) as theone
          ORDER BY ABS(theone.rank - t.rank)
          LIMIT N
         ) t
    ORDER BY t.rank;