mysql随机获取一条或者多条数据SQL分析

从数据库随机取5条用户数据

SELECT * FROM user WHERE id >= ((SELECT MAX(id) FROM user)-(SELECT MIN(id) FROM user)) * RAND() + (SELECT MIN(id) FROM user)  LIMIT 5

这段SQL语句是在网上找的,想请问一下 id >= ((SELECT MAX(id) FROM user)-(SELECT MIN(id) FROM user)) * RAND() + (SELECT MIN(id) FROM user) 是怎么达到随机获取的?TKS

如果我改成 id >= 1,则顺序取出了id为1,2,3,4,5的用户!

这段sql

SELECT * FROM user WHERE id >= ((SELECT MAX(id) FROM user)-(SELECT MIN(id) FROM user)) * RAND() + (SELECT MIN(id) FROM user)  LIMIT 5

是执行了5次吗?如果一次的话,结果应该就不是随机的了,就像id >=?某个值了,取出来是连续的!

clipboard.png

clipboard.png

阅读 12.8k
4 个回答

先说我测试的结论,LIMIT 5调用了很多次where后的查询条件。

这样LIMIT 5的含义我用了一个例子证实了一下。

例子:
1.创建test表,两个字段:主键id,count
2.创建mysql function

CREATE FUNCTION `fun` ()
RETURNS INTEGER
BEGIN
    declare num float;
    insert into test(count) values(1);
    select (((SELECT MAX(id) FROM user)-(SELECT MIN(id) FROM user)) * RAND() + (SELECT MIN(id) FROM user)) into num;
RETURN num;
END

3.执行一下语句
SELECT * FROM user WHERE id >= (select fun()) LIMIT 5

4.看一下test表,
id count
1 1
2 1
3 1
4 1
5 1
6 1
7 1
8 1
9 1
10 1
11 1
12 1
13 1
14 1

至于为什么会执行这么多次function,我认为是跟limit的机制有关
明白题目的意思了,理解错误抱歉。

更新:我的user表是14条数据,现在目测的原因是LIMIT前的where条件,同LIMIT函数遍历了整个表单,也是就是执行了14次

我来说下我的理解吧

SELECT * FROM user WHERE id >= ((SELECT MAX(id) FROM user)-(SELECT MIN(id) FROM user)) * RAND() + (SELECT MIN(id) FROM user)  LIMIT 5;

关于最大减去最小值乘以随机值获取随机数的概念就不说了,只针对上面的sql在mysql解析层的处理作下说明,实际上mysql是做了这样的处理(因为是mysql在解析sql时做的优化,并不一定就是下面的sql,下面的sql只是本人理解大致的思路):

SELECT user.* FROM user join (select round(((SELECT MAX(id) FROM user)-(SELECT MIN(id) FROM user)) * RAND() + (SELECT MIN(id) FROM user)) id from user) user_tmp on user.id=user_tmp.id  order by user.id LIMIT 5;

就是先根据rand()和id获取一遍随机数,再跟原表关联,最后取出5个值,因为是随机取,所以你的id值越平均,数据量越大,最后limit之前获取的id值就会越接近整表数据量的一半,limit 5取到的结果也越接近。

可以这么验证一下获取随机数的逻辑:

select distinct round(((SELECT MAX(id) FROM user)-(SELECT MIN(id) FROM user)) * RAND() + (SELECT MIN(id) FROM user)) id from user;
和
SELECT * FROM user WHERE id >= ((SELECT MAX(id) FROM user)-(SELECT MIN(id) FROM user)) * RAND() + (SELECT MIN(id) FROM user)

分别执行看下结果集是不是比较接近。

其实很好理解啊,按照sql的执行顺序,肯定是先执行((SELECT MAX(id) FROM user)-(SELECT MIN(id) FROM user)) * RAND() + (SELECT MIN(id) FROM user) as a,然后执行id>=a,limit 5就是去连续的5个值啊。

新手上路,请多包涵

你可以select top N * from table_name order by newid(); ----N是一个你指定的整数,随机排序后表是取得随机记录。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题