共计 1342 个字符,预计需要花费 4 分钟才能阅读完成。
随机查询,方法可以有很多种。比如,查询出所有记录,然后随机从列表中取 n 条记录。使用程序便可实现。可是程序实现必须查询出所有符合条件的记录(至少是所有符合条件的记录 id),然后再随机取出 n 个 id,查询数据库。但是效率毕竟没有数据库中直接查询得快。下面介绍 MySQL 中怎样随机查询 n 条记录。
1. 最简单的办法 order by rand(), 示例
select * from question q where q.`level`=1 order by rand() limit 1;
此写法,可以将查询出的结果集打乱,limit n 条记录后,得到 n 条随机的记录,这 n 条记录也是随机顺序的,就是效率有点慢,但是很随机。
2. 如果记录 id 保持连续增长,中间不间断,则可以用其它方式替代上述语句,示例
# 随机查询(记录大于某个数,效率高)
select q1.* from question q1 inner join (select (min(q2.id) + round(rand()*(max(q2.id) – min(q2.id)))) as id from question q2 where q2.`level`=1) as t
on q1.id >= t.id limit 1;
# 效率略低
select q.* from question q where q.id > (select t.id from (
select (min(q2.id) + round(rand()*(max(q2.id) – min(q2.id)))) as id from question q2 where q2.`level`=1
) t) limit 1;
# 效率极低,比 order by rand 还低(可能针对每条记录都作了子查询,结果不不连续,很随机)
select q.* from question q where q.id > (select (min(q2.id) + round(rand()*(max(q2.id) – min(q2.id)))) from question q2 where q2.`level`=1) limit 1;
法 2 的实现原理是,找出符合条件的记录的 id 范围 [minId,maxId], 然后随机生成一个 id, 使 id 在范围内,算法为 id=minId+[0,maxId-minId],[0,maxId-minId] 可使用 round 四舍五入函数和 rand 随机函数实现。然后大于等于此 id 的记录既是符合条件的随机的记录。上述写法仅针对查询出一条记录。如果查询出 n 条记录则 sql 语句改为:
select q1.* from question q1 inner join (select (min(q2.id) + round(rand()*(max(q2.id)-2 – min(q2.id)))) as id from question q2 where q2.`level`=1) as t
on q1.id >= t.id limit 3;
如上,随机取连续的 3 条记录,max 的值减掉二,就是使范围缩小 2,保证随机出来的 id,大于等于它时仍可查出 3 条记录。
附上随机函数的测试代码:
select 10*RAND(); #[0,10)
select FLOOR(10*RAND());#[0,9]
select CEILING(10*RAND()); #[1,10]
select ROUND(10*RAND()); #[0,10]
: