Question

Mysql: i need to get the offset of a item in a query.

I have a image gallery: this show 6 image per stack, so when i request image 22 it shows images from 18 to 24. It should first get the offset of the image 22, then get the images from 18 to 24.

Another example: i request the image number 62(and offset 62), it will select images with offset from 60 to 66.

Is possible with a single query?

The main important thing is to get the offset value of the item that has its id equal to a number.

Thanks ;)

EDIT: select * from images order_by updated_at offset(here i need to get the offset of the image id in this query, and the make some calculation... this is what i need, if is possible.. :d)

EDIT2: Now I understand that I need 2 queries:

1º: get the offset of the image within the query with my custom order

2º: get the images using the offset from the first query... this I can make it alone, the first one is the problem.. :s

Was it helpful?

Solution

If your images have sequential IDs, you may want to do the following:

SELECT    * 
FROM      images 
WHERE     id >= ((? DIV 6) * 6) AND 
          id < (((? DIV 6) + 1) * 6)
ORDER BY  id;

Replace the ? parameter in the above query with the ID of the image requested.


UPDATE: It seems that your images are not ordered by a sequential ID, but by a timestamp. Unfortunately it looks like MySQL does not support variable expressions in the LIMIT clause (Source). One option would be to use a prepared statement:

PREPARE stmt FROM 
" SELECT    * 
  FROM      images
  ORDER BY  updated_at
  LIMIT     ?, 6";

SET @lower_limit := ((22 DIV 6) * 6);

EXECUTE stmt USING @lower_limit;

Another option could be:

SET @row = 0;

SELECT    * 
FROM      images 
WHERE     (@row := @row + 1) BETWEEN ((3 DIV 6) * 6) + 1 and (((3 DIV 6) + 1) * 6)
ORDER BY  updated_at;

OTHER TIPS

EDIT: It appears MySQL does not allow this kind of expression in the OFFSET clause. If you can use a prepared statement (either directly in SQL or in another language), you can make the calculation beforehand and use it. See Daniel's answer for that. I'm leaving this answer here because of the other useful information.

What you are looking for is called pagination. In MySQL you can do it with the LIMIT and OFFSET keywords:

SELECT   image
FROM     images
ORDER BY updated_at
LIMIT    6
OFFSET   (DIV(?, 6) * 6)

Replace ? with the requested image index. Note that this will give images with offsets 60, 61, 62, 63, 64, 65 when you ask for image 62. I assumed the last offset you gave in the examples was exclusive. You should adjust accordingly if I made the wrong assumption.

And a little explanation:

LIMIT makes the query return only the given number of results. Because you always want six, that makes it easy.

OFFSET makes the query return only results from the given offset. The calculation does integer division by six and multiplies by six. This results in the previous multiple of six of the given number, exactly what you want.

I may not understand you, but why do you have to do everything in MySQL?

Let's assume you use LAMP:

$pagination_start = (int)(floor($id_requested / 6)*6);
$offset_array = ($id_requested % 6);
$offset_mysql = $pagination_start + $offset_array;

Now you have start of your pagination in $pagination_start [i.e. 60] and requested image offset [i.e. 62] in $offset_mysql:

SELECT   image
FROM     images
ORDER BY updated_at DESC
LIMIT    $pagination_start, 6

Now in return, you get an array cotaning 6 images and the one requested is at $result[$offset_array].

SELECT   image
FROM     images
ORDER BY updated_at
LIMIT    6, FLOOR($number / 6 ) * 6;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top