I have a table with about 50k rows. There's a column called status
. Its value can be either 0
or 1
. I need to grab a random row that has status = 0
.
SELECT * FROM table WHERE status = 0 ORDER BY RAND() LIMIT 1
is obviously too slow.
So, what I did so far was, get the count of the amount of rows that have status = 0
using SELECT COUNT(status) FROM table WHERE status = 0
Now I now that I have 209 rows that have status = 0
, but how can I work on these rows?
I'd would like to order these 209 rows, and make my php script get a random row number between the numbers 0 and 209, but I'm not sure how I can achieve that..
Did you try this?
SELECT t.*
FROM table t
WHERE status = 0
ORDER BY RAND()
LIMIT 1;
Sorting 209 should be quite fast.
EDIT:
Getting a random value efficiently is challenging. If you have an index on table(status)
, you can try an approach like this:
SELECT t.*
FROM table t cross join
(select count(*) as allcnt from table where status = 0) const
WHERE status = 0 and
RAND() < 10/allcnt
ORDER BY RAND()
LIMIT 1;
The rand()
in the where
clause is quite fast ( RAND()
is fast, sorting is slow). It should greatly reduce the number of rows to an expected value of 10 -- which means that you are almost certain to get a row (99.99+%, I think) when you run it. This is also simpler than the variable method.
The variable method involves a subquery, which incurs its own overhead for reading and writing the derived table. The idea is to enumerate the rows and then choose one index randomly:
SELECT t.*
FROM (select t.*, @rn := @rn + 1 as rn
from table t cross join
(select @rn := 0, @rand := rand()) const
where status = 0
) t cross join
(select count(*) as allcnt from table where status = 0) const
WHERE floor(1 + @rand * const.allcnt) = rn;
我知道这需要两个查询,但是您可以尝试一下并对其进行基准测试:获取与status = 0匹配的行的总数,从PHP获取一个介于0和number-1之间的随机数,并使用限制1和php生成的随机值的偏移量。
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.