Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Consistent random ordering in a MySQL query

Tags:

random

mysql

I have a database of pictures and I want to let visitors browse the pictures. I have one "next" and one "previous" link.

But what I want is to show every visitor anther order of the pictures. How can I do that? If I will use ORDER BY RANDOM() I will show sometimes duplicate images.

Can someone help me please? Thank you!

like image 875
Nathaniel Avatar asked May 28 '11 09:05

Nathaniel


People also ask

Why is MySQL using filesort?

Use of filesort to Satisfy ORDER BY If an index cannot be used to satisfy an ORDER BY clause, MySQL performs a filesort operation that reads table rows and sorts them. A filesort constitutes an extra sorting phase in query execution.

Does ORDER BY use index MySQL?

Yes, MySQL uses your index to sort the information when the order is by the sorted column. Also, if you have indexes in all columns that you have added to the SELECT clause, MySQL will not load the data from the table itself, but from the index (which is faster).

How do I sort in MySQL?

The ORDER BY keyword is used to sort the result-set in ascending or descending order. The ORDER BY keyword sorts the records in ascending order by default. To sort the records in descending order, use the DESC keyword.


2 Answers

You can try to use seed in random function:

SELECT something FROM somewhere ORDER BY rand(123)

123 is a seed. Random should return the same values.

like image 104
izi Avatar answered Oct 11 '22 21:10

izi


The problem arises from the fact that each page will run RAND() again and has no way of knowing if the returned pictures have already been returned before. You would have to compose your query in such a way that you can filter out the pictures already presented on the previous pages, so that RAND() will have fewer options to choose from.

An idea would be to randomize the pictures, select the IDs, store the IDs in the session, then SELECT using those IDs. This way, each user will have the pictures randomized, but they will be able to paginate through them without re-randomizing them on each page.

So, something like:

  1. SELECT id FROM pictures ORDER BY RAND() LIMIT x if you don't have the IDs in the session already
  2. Store the IDs in the session
  3. SELECT ... FROM pictures WHERE id IN (IDs from session) LIMIT x

Another idea is to store in session the IDs that the user already saw and filter them out. For example:

  1. SELECT ... FROM pictures ORDER BY RAND() LIMIT x if the session doesn't contain any ID
  2. Append the IDs from the current query to the session
  3. SELECT ... FROM pictures WHERE id NOT IN (IDs from session) ORDER BY RAND() LIMIT x

Another way seems to be to use a seed, as izi points out. I have to say I didn't know about the seed, but it seems to return the exact same results for the exact same value of the seed. So, run your usual query and use RAND(seed) instead of RAND(), where "seed" is a unique string or number. You can use the session ID as a seed, because it's guaranteed to be unique for each visitor.

like image 45
rid Avatar answered Oct 11 '22 19:10

rid