I am trying to get a random row in MySQL. Here is my approach:
SELECT *
FROM users
WHERE id =
(SELECT floor((max(id) - min(id) + 1) * rand()) + min(id)
FROM users);
This can return an empty set when there are gaps in the ids. I am fine with that. However,
- I don't have gaps and I still get an empty set rather frequently.
- More disturbing: I will get two or more results every once in a while.
What is the reason for this strange behavior? How, do I get it right?
Note:
- the table is quite big (10^6 ... 10^7); I can't use any of the obvious, and known, solutions based on random ordering or even based on using count().
- I'am stuck with MySQL, I don't care how it's done on the client side ruby/PHP/whatever.
- I tried to cast the floating types, but it did not help.
- The corresponding PostgreSQL variant (random instead of rand, and some type casts) works fine.
This avoids repeated evaluation of
random()
during the aggregation and should be faster, too, asmin(id)
andrandom()
are only evaluated once.How about:
or similar?
Pretty much it should limit you to one result, and if it hits a gap (somehow), then it'll just take the next available one.
Try this one -
Will return a random row.
I suspect that this is because
RAND()
is being evaluated for every row in the USERS table in the main query. I suggest: