mysql 以自增id等于某个random()函数算出的值为条件查出两条数据
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()函数算出的值为条件查出两条数据的更多相关文章
- mysql 数据库自增id 的总结
有一个表StuInfo,里面只有两列 StuID,StuName其中StuID是int型,主键,自增列.现在我要插入数据,让他自动的向上增长,insert into StuInfo(StuID,Stu ...
- MYSQL获取自增ID的四种方法
MYSQL获取自增ID的四种方法 1. select max(id) from tablename 2.SELECT LAST_INSERT_ID() 函数 LAST_INSERT_ID 是与tabl ...
- MySQL 使用自增ID主键和UUID 作为主键的优劣比较详细过程(从百万到千万表记录测试)
测试缘由 一个开发同事做了一个框架,里面主键是uuid,我跟他建议说mysql不要用uuid用自增主键,自增主键效率高,他说不一定高,我说innodb的索引特性导致了自增id做主键是效率最好的,为了拿 ...
- mysql数据库自增id重新从1排序的两种方法
mysql默认自增ID是从1开始了,但当我们如果有插入表或使用delete删除id之后ID就会不会从1开始了哦. 使用mysql时,通常表中会有一个自增的id字段,但当我们想将表中的数据清空重新添 ...
- DBS-MySQL:MYSQL获取自增ID的四种方法
ylbtech-DBS-MySQL:MYSQL获取自增ID的四种方法 1.返回顶部 1. 1. select max(id) from tablename 2.SELECT LAST_INSERT_I ...
- mysql数据库表自增ID批量清零 AUTO_INCREMENT = 0
mysql数据库表自增ID批量清零 AUTO_INCREMENT = 0 #将数据库表自增ID批量清零 SELECT CONCAT( 'ALTER TABLE ', TABLE_NAME, ' AUT ...
- mysql 数据库查询最后两条数据
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u011925175/article/details/24186917 有一个mysql数据库的 ...
- 【sql】mysql数据库做两条数据替换的操作,不使用第三方变量
需求: 1.将数据库中两条数据中的唯一约束列 做值的替换 原始思想: 将两条数据查出来,在程序中设置第三方变量,进行两条数据的替换,然后将原始两条数据删除,将新的两条替换后的数据插入. 新思想: 1 ...
- 为什么数据库能查出两条id相同的数据
sql如下: SELECT t.*,d.name as "workName" FROM t_traceability_slice t LEFT JOIN sys_departmen ...
- mysql 返回自增id
String dateNow= DateTime.Now.ToString("yyyyMMddhhmmss"+ new Random().Next(1, 99)); //随机数 ...
随机推荐
- python如何提取word内的图片
解压.docx文件实现提取图片 前言 .docx文件其实也就是一个压缩文件,当我们将一个.docx文件直接解压后可以看到如下目录 其中我们要找的图片就在word/media目录内,如图 所以,要提取w ...
- 2022-3-29内部群每日三题-清辉PMP
1.一名高管,也是上报升级的联系人,在生产启动期间加入一个敏捷团队.在下一个sprint之前,该高管向团队询问应包含的特性.该高管应已参加什么会议? A.回顾会议. B.每日scrum会议. C.Sp ...
- web server 接口调用
1. 生成客户端代码 2.调用接口 import javax.xml.ws.Service;public static NotificationServiceDevImplPortType mokaA ...
- SQL-建表注释
ddl 是对表结构的操作 create(创建)命令.alter(修改)命令.drop(删除)dml 是对表数据的操作 insert(插入)命令.update(更新)命令.delete(删除) alte ...
- 第三课 Hello World显示
HelloWorld 1.新建文件件 2.新建java文件 3.编写代码 public class Hello{ public static void main(String[] args){ Sys ...
- AD9834配置
SPI设置 注意,虽然手册上CPOL(CLK空闲时电平)为低,但实测是是高电平 连接 SYNC 为片选引脚,使用时拉低 FSE/PSE为频率与相位寄存器选择,均拉低即可 void SPI_Write_ ...
- oracle 实例无法启动和初始化
1 先看oracle的监听和oracle的服务是否都启动了.启动oracle监听:cmd的命令行窗口下,输入lsnrctl start,回车即启动监听.2 查看oracle的sid叫什么,比如创建数据 ...
- 分布式-Etcd介绍
Etcd客户端基本操作 提供了如下操作接口: put - 添加一个新的 key-value 到存储中 get - 获取一个 key 的 value delete - 删除节点 range - 获取一个 ...
- 前端自动化测试框架Cypress环境搭建
1. 下载安装node.js(之前的随笔里写过安装nodejs具体步骤这里不过多介绍了) 下载地址:https://nodejs.org/en/ 2.安装路径(这是安装完成nodejs的路径) 3. ...
- Jmeter一、开源软件的崛起
一.jmeter自身特点: 1.开源,轻量级,更适合自动化和持续集成. 2.学习难度大. 3.资料少.多英文. 二.性能测试工具选型的原则 1.成本: a.工具成本 b.学习成本 2.通信协议: a. ...