SELECT
id
FROM
users
WHERE
id = FLOOR(
rand() * (
(SELECT max(id) FROM users) - (SELECT min(id) FROM users)
) + (SELECT min(id) FROM users)
);

这是你写的SQL,我用手边的表查得时候不仅有两个结果的,还有空的,还有三个结果的.我也有点费解了.这种谜一样的问题是怎么出现的??

创建了一个单列表.一共1000条数据.

下面我们来复现问题

可以看到问题就出现在了这里,id=floor(rand()*1000)在我们的直观印象中,应该等于一个值.然而实际上不是这样,
在这里,floor(rand()*1000)是在变化的
也就是说,这1000行数据,执行这条语句的时候,是这样的操作:

  • 判断第一行的id 1是否等于floor(rand()*1000),
  • 判断第二行的id 2是否等于floor(rand()*1000),
  • 判断第三行的id 3是否等于floor(rand()*1000),

我们只看这三次操作就够了,后边的floor(rand()*1000)是在不断变化的,第一次操作也许等于2,第2次操作可能等于1,第三次操作可能等于3.写成代码的话就是这样.

function rand() {
// 随机生成一个数N
return N
}
for (let i = 1; i <= 1000; i++) {
if (i == rand()) {
//选中这一条记录
//可以看到,每次匹配的时候,都会执行一次rand()
} }
//而我们想要的其实是 let selected = rand() for (let i = 1; i <= 1000; i++) {
if (i == selected) {
//选中这一条记录
//每次都和已选出且不会变动的随机值进行比较
} }

在mariadb的文档中也提到,In a WHERE clause, RAND() is evaluated each time the WHERE is executed.

这就造成了id看似是在和一个值比较,实际上是1000个id分别和1000个随机数进行比较,两个数刚好相等的概率是1*1/1000,而刚好比较一千次,所以每次查到的结果期望值为1(个),但是这并不是稳定的,所以才会出现有时候查不到,有时候查到两条三条这中情况.

解决问题

知道了问题发生的原因,解决的思路自然就出现了,让rand()只计算一次.

第一个方法,使用join

SELECT
`测试表`.`id`
FROM
`测试表`
INNER JOIN (
SELECT
floor(rand() *(MAX(id) - MIN(id))) + min(id) AS id
FROM
`测试表`
) AS tmp
WHERE
`测试表`.`id` = `tmp`.`id`;

第二个方法,使用会话变量.


SET @rnd = RAND(); SELECT
id
FROM
`测试表`
WHERE
id = (
SELECT
floor(@rnd * (MAX(id) - MIN(id))) + min(id)
FROM
`测试表`
);

引用自:

https://segmentfault.com/q/1010000016824164?utm_source=tag-newest

https://stackoverflow.com/questions/47503471/mysql-where-rand-behaviour

https://stackoverflow.com/questions/49342846/strange-behavior-or-rand-in-mariadb-single-rand-delivers-more-than-1-result

mysql 以自增id等于某个random()函数算出的值为条件查出两条数据的更多相关文章

  1. mysql 数据库自增id 的总结

    有一个表StuInfo,里面只有两列 StuID,StuName其中StuID是int型,主键,自增列.现在我要插入数据,让他自动的向上增长,insert into StuInfo(StuID,Stu ...

  2. MYSQL获取自增ID的四种方法

    MYSQL获取自增ID的四种方法 1. select max(id) from tablename 2.SELECT LAST_INSERT_ID() 函数 LAST_INSERT_ID 是与tabl ...

  3. MySQL 使用自增ID主键和UUID 作为主键的优劣比较详细过程(从百万到千万表记录测试)

    测试缘由 一个开发同事做了一个框架,里面主键是uuid,我跟他建议说mysql不要用uuid用自增主键,自增主键效率高,他说不一定高,我说innodb的索引特性导致了自增id做主键是效率最好的,为了拿 ...

  4. mysql数据库自增id重新从1排序的两种方法

    mysql默认自增ID是从1开始了,但当我们如果有插入表或使用delete删除id之后ID就会不会从1开始了哦.   使用mysql时,通常表中会有一个自增的id字段,但当我们想将表中的数据清空重新添 ...

  5. DBS-MySQL:MYSQL获取自增ID的四种方法

    ylbtech-DBS-MySQL:MYSQL获取自增ID的四种方法 1.返回顶部 1. 1. select max(id) from tablename 2.SELECT LAST_INSERT_I ...

  6. mysql数据库表自增ID批量清零 AUTO_INCREMENT = 0

    mysql数据库表自增ID批量清零 AUTO_INCREMENT = 0 #将数据库表自增ID批量清零 SELECT CONCAT( 'ALTER TABLE ', TABLE_NAME, ' AUT ...

  7. mysql 数据库查询最后两条数据

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u011925175/article/details/24186917  有一个mysql数据库的 ...

  8. 【sql】mysql数据库做两条数据替换的操作,不使用第三方变量

    需求: 1.将数据库中两条数据中的唯一约束列  做值的替换 原始思想: 将两条数据查出来,在程序中设置第三方变量,进行两条数据的替换,然后将原始两条数据删除,将新的两条替换后的数据插入. 新思想: 1 ...

  9. 为什么数据库能查出两条id相同的数据

    sql如下: SELECT t.*,d.name as "workName" FROM t_traceability_slice t LEFT JOIN sys_departmen ...

  10. mysql 返回自增id

    String dateNow=  DateTime.Now.ToString("yyyyMMddhhmmss"+  new Random().Next(1, 99)); //随机数 ...

随机推荐

  1. 正在运行转换: System.Runtime.Remoting.RemotingException: 无法加载类型“EnvDTE._DTE

    在编写T4,引用envdte时,遇到如下错误,解决方案:右击引用中的envdte,属性中将"嵌入互操作类型"为false,重新编译库即可. 错误信息如下: 严重性    代码   ...

  2. 用find和xargs处理文件名中带空格的文件

    我们经常用find和xargs来进行批处理文件. 常见的用法如:find ./ -name ".jpg" | xargs cp -t ./JPEGImages ,实现将当前目前下所 ...

  3. rdlc 中文在win10中显示异常,在非win10中显示正常

    RDLC中的默认字体Arial. 在win10中,RDLC为Arial时,显示中文会异常,这个时候,只需要将Font修改为中文字体就可以了,例如修改为宋体.

  4. elm上传图片,只能上传一张,隐藏+上传框

    效果: 上传后,隐藏+号,禁止继续上传: 移除当前已上传的后,重新显示+号,可以继续上传: 代码: css : 隐藏上传的 + 号 变量: 注: 利用 hideUpload 控制 + 号的css   ...

  5. mybati之sql集合

    mybatis 详解(五)------动态SQL - YSOcean - 博客园 (cnblogs.com) mybatis参数注入: 根据参数名称 使用#{} 注入参数 <insert id= ...

  6. Java基础——方法

    package com.zhao.demo; public class Demo07 { /* public static void main(String[] args) { //getSum(10 ...

  7. Vue3.0 里为什么要用 Proxy API 替代 defineProperty API?

    响应式优化. a. defineProperty API 的局限性最大原因是它只能针对单例属性做监听. Vue2.x 中的响应式实现正是基于 defineProperty 中的 descriptor, ...

  8. react module.scss文件中弹窗中 keyframes动画不生效,

    以下修改,亲测有效非弹窗内动画写法 .submit_btn{   animation: submit_btn 1.5s infinite;     -webkit-animation: submit_ ...

  9. go实现ls

    package mainimport ( "fmt" "log" "os")func main () { f,err :=os.Open(& ...

  10. 我的第一周C语言作业

    这个作业属于哪个课程 https://edu.cnblogs.com/campus/zswxy/SE2020-2 这个作业要求在哪里 https://edu.cnblogs.com/campus/zs ...