Considering the following table:
rowid | text | group
1 | a | 1
2 | b | 2
3 | c | 2
4 | d | 3
5 | e | 4
6 | f | 1
7 | g | 1
8 | h | 4
9 | j | 5
10 | k | 2
11 | i | 3
12 | l | 3
Now imagine I want the row number of rowid 6 (for use in eg. pagination). Since it’s auto incrementing, it’d be very simple to just select where rowid = 6, but in this case I want to know what row number it has in group 1.
Obviously it’s easy to do this by eye in such a small example (it’s row number 2).
Row number 1 would be rowid = 1.
Row number 2 would be rowid = 6.
Row number 3 would be rowid = 7.
My first thought was something like this:
SELECT
tmp.rowid,
tmp.text,
tmp.group,
tmp.row_number
FROM
(
SELECT
`rowid`,
`text`,
`group`,
(@rowNumber := @rowNumber + 1) as `row_number`
FROM
`my_table`,
(SELECT @rowNumber := 0) as `r`
WHERE
`group` = 1
ORDER BY
`rowid` DESC
) as `tmp`
WHERE
tmp.rowid = 6
Which will give the right result (in row_number), but on a big table (half a million records) this will take a good 2.5 seconds onn a quick server, as it has to first collect all 500,000 entries, and THEN select row id 6.
What should I do to make this quicker/better?
The solution is actually very simple.
SQL
NOTE
You need to have a row with an incrementing value (such as a timestamp, an incrementing ID, etc.).
Here we convert the original
ORDER BY rowid DESCtoWHERErowid>= '6'. If you useORDER BYascending, you’ll want to use<=instead.The query takes 0.00002 seconds, and returns the correct row number (in
row_number). If you want thetextandgroupcolumns, you’ll have to either make this a subquery or make an additional query that selectsWHERE rowid = 6.