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)); //随机数 ...
随机推荐
- vue 中 watch 和 watchEffect 区别
vue 中 watch 和 watchEffect 区别 * watch 需要先指明需要侦听的数据源,watchEffect 不需要,只要传入的函数带有依赖就会自动追踪. * watchEffect ...
- java8 stream流的使用
List<Paper> list = new ArrayList<>();list.add(new Paper("m",2L));list.add(new ...
- Vmware 虚拟机Ubuntu系统,解决忘记用户名和密码解决办法
1.在开机界面按住shift,会加载grub的启动界面,找到Advaced options for Ubuntu选项.按"e" 进入编辑模式. 2.光标移动至ro,改为rw,(Li ...
- iOS 15 UI适配
1. UINavigationBar 在iOS 15中,UINavigationBar默认为透明.在滑动时会有模糊效果.如果想要一直就是模糊效果,可以通过改变scrollEdgeAppearance属 ...
- 学习lua-04,json.util merge方法对集合处理的实际应用,及tostring方法
local jsonutil = require("json.util") local merge = require("json.util").merge l ...
- spring boot权限设计资源
源代码 https://github.com/2237995998/education 博客说明 https://blog.csdn.net/weixin_45138601/article/detai ...
- java 类对象四种方法加载方式
public static void main(String[] args) throws Exception { //第一种 //这里需要做异常处理,或的加载类的类对象类. Class<?&g ...
- noi 1.1 6 空格分隔输出
描述 读入一个字符,一个整数,一个单精度浮点数,一个双精度浮点数,然后按顺序输出它们,并且要求在他们之间用一个空格分隔.输出浮点数时保留6位小数. 输入 共有四行:第一行是一个字符:第二行是一个整数: ...
- dead code?
public static void main(String[] args) { DriverBase dbase = new DriverBase(); dbase.driverBase(); dr ...
- POJ--1852-c++实现
因为蚂蚁的朝向不明确,所以,可以根据需要假定朝向方向 首先,当每只蚂蚁朝着离自己最近的端点前进,且不回头则,所需总时间最少 当每只蚂蚁朝着离自己最远的端点前进,所需时间最多,在这期间,会碰到其他蚂蚁, ...