MySQL如何实现随机查询时有对查询条件的判断?

首先,实现随机的方法我知道.问题是如何在查询随机数据时能够对条件进行判断

举个例子

我想让每次返回的数据都是随机的且要满足下面的一个条件.不要写死一个一个值去判断,不去count()具体的值

条件 : 随机查询的数据满足每个专业的最少有一个人

图片说明

我的想法是

  • 先查询出所有的数据(随机)
  • 再通过一个存贮函数来判断条件是否达到
  • 达到后,结束

    通过下面的代码,能够查询出每个专业的人数,可以用来做判断,是否满足条件,但是这是查询全部的.

    当我想要查询只要10个人时,下面的代码查的是所有人.

    但是,我要是先随机查询出10个人,那么这10个人不一定会满足条件.如果一直随机查询直到满足条件,那就太浪费资源了

SELECT  COUNT(t.zhuanye) c
FROM t_expert AS t
GROUP BY t.zhuanye
HAVING c>=2

现在,我疑惑的地方是这个存贮函数如何写,怎么样才能在查到相应的数据后,停止查询.

我对MySQL只是简单了解.这个问题,困惑我很久了.

4个回答

遇到复杂逻辑的需求.不要寄托于数据库.而且数据对于一些不太复杂的逻辑来讲速度很快.

但是,一旦涉及我这种看起来还可以,但实际上要求很是复杂.

不如先把所有数据查出来,再去按照需求去自己取值.

但是这就有涉及到**另一个问题**

  • 在数据量比较大的时候,不能将所有的数据都一次性取出来.只能取一部分.
  • 而这一部分数据在遍历完之后,可以能也不会满足需求.
  • 这时,还是需要再去取数据.又增加了数据库的访问次数.而且还不一定需要多少次.

所以,我想,按分层查询,假设男女最少各为3人.
那么,为了避免1000个男的,就只有6个女的这种情况(只为举例说明)
所以,我先查询男的取3个,再查询女的取3个.

但是这种情况,只能时候,字段值比较少的时候,多了还是麻烦.我现在还没有想好.等有空闲了,我再好好琢磨一下


2018-12-19

我想到,可以使用使用 IN() OR IN() 来减少数据量,查询时可以使用MySQL上的 FIND_SET_IN() 函数来简化

建议不要把简单问题复杂化,往往2个简单的需求组合到一起就变成一个复杂的问题了。
我觉得可以考虑先随机全部数据,然后按照条件要求,在后台或存储过程实现。而不是硬要用SQL实现。

qq_34120430
居十四 对的,我也是这么想的.如果硬要用SQL语句实现.十分的复杂.在数据量不多的情况下,可以先把数据都查出来.然后在具体的实现细节后台处理
一年多之前 回复
SELECT * FROM test WHERE id >= (SELECT floor(RAND() * (SELECT MAX(id) FROM test)));

上边的这个代码,是根据后边的随机数,查询随机的数据库记录条数。但是要强调的是,是连续的,就是从随机数开始一直显示到最后一条记录。

SELECT * FROM test WHERE id >= (SELECT floor(RAND() * (SELECT MAX(id) FROM test))) ORDER BY id LIMIT 0,5;

第二条,sql 语句 。就会限制数据库的查询条数。像我写的就是选取了5条。

但是,还会有一些问题,比如,我的数据库总共有10条信息记录,限制是查询 5 条,随机数是7的话,只会有第7、8、9、10,这三条记录。
如果随机数是5,则会显示5、6、7、8、9 这5条记录。

只做一个思路的参考,不肯定能解决你的问题,我啥问题,一起探讨。

Roobert_Chao
Roobert_Chao 回复居十四: 在查询的时候约束条件设置满足后可以查询出一些内容,还可以对sql 中闯入一个数组,这个数组 中存随机数,然后再根据随机数查询。
一年多之前 回复
qq_34120430
居十四 第二个sql提示了我,确实按ID查是连续的.不过请问有没有遇到过类似的问题?需要随机查询的几个人,需要满足这几个人满足一些约束条件.就像必须有男或女的人数大于等于2.
一年多之前 回复

随机查询,方法可以有很多种。比如,查询出所有记录,然后随机从列表中取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条记录。

如果 maxId-(n-1)-minId为负数,就是说数据记录范围内没有n条记录,则上述语句报错,改进版如下:

select q1.* from question q1 inner join (
select (min(q2.id) + round(rand()* ( case when (max(q2.id)-2)>min(q2.id) then max(q2.id)-2 - min(q2.id) else 0 end ))) as id,min(q2.id) as minId,max(q2.id) as maxId from question q2 where q2.level=2
) as t
on q1.id >= t.id and q1.id between t.minId and t.maxId limit 3;

附上随机函数的测试代码:

select 10*RAND(); #[0,10)
select FLOOR(10*RAND());#[0,9]
select CEILING(10*RAND()); #[1,10]
select ROUND(10*RAND()); #[0,10]

qq_34120430
居十四 你这个其实是说的随机查询,我的问题是怎么在随机查询的同时来判断是否满足相应的条件.
一年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问