I'm trying to add pagination to my points system (100 results per page) and came up with this :
SELECT A.username, A.points
FROM users A
INNER JOIN (
SELECT points
FROM users
WHERE points <> 0
ORDER BY points DESC
LIMIT $start, $limit
)B
USING (points)
The username and points columns have indexes.
When running this query (LIMIT 100, 100), it returns this (in phpMyadmin) :
Showing rows 0 - 29 ( 124 total, Query took 0.0001 sec)
I'm asking for 100 rows, but it's returning 124. I've never seen this before.
Here is what EXPLAIN shows :
+----+-------------+------------+-------+---------------+--------+---------+----------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+--------+---------+----------+------+--------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 100 | |
| 1 | PRIMARY | A | ref | points | points | 2 | B.points | 2 | |
| 2 | DERIVED | users | index | points | points | 2 | NULL | 200 | Using where; Using index |
+----+-------------+------------+-------+---------------+--------+---------+----------+------+--------------------------+
EXPLAIN shows 100 rows as well, but when outputing the array, it's still returning 124 results.
Any ideas how I can fix this?
Best Answer
If you only want the 100 rows (with offset 100), you don't need a subquery. Use what you name
B
, adding theusername
:If you have an index on
(points, username)
, it will be pretty fast (at least when the offset is not huge).The query you have is bringing more than 100 rows because, as @Phil pointed, you are using a subquery. You are joining table
A
(which probably has thousands or millions of rows) with the (derived) tableB
(which has 100 rows at maximum). But the joining is done usingpoints
which is not unique on the table. So, for some rows of tableB
, there are more than one rows fromA
joined.