居十四
2018-12-17 10:03
采纳率: 50%
浏览 732
已采纳

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

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

举个例子

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

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

图片说明

我的想法是

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

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

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

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

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

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

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

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

4条回答 默认 最新

  • 居十四 2018-12-18 10:31
    已采纳

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

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

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

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

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

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

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


    2018-12-19

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

    已采纳该答案
    打赏 评论
  • Roobert_Chao 2018-12-17 10:48
    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条记录。

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

    打赏 评论
  • devmiao 2018-12-17 12:17

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

    打赏 评论
  • bczzm 2018-12-18 06:48

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

    打赏 评论

相关推荐 更多相似问题