mysql - MariaDB 中的奇怪行为或 RAND : Single RAND delivers more than 1 result

标签 mysql random

运行以下查询时:

SELECT productid 
FROM product 
WHERE productid=ROUND(RAND()*(SELECT MAX(productid) FROM product));

结果应该是 0 或 1 个结果(0 由于数据间隙,1 如果找到记录),但是它会多次产生多个结果(非常容易重现,90% 的查询有超过1 个结果)。

示例输出:

+-----------+
| productid |
+-----------+
|     11701 |
|     20602 |
|     22029 |
|     24994 |
+-----------+

(DB中的记录数约为30k)。

运行单个 SELECT RAND() 始终会产生单个结果。

解释:

explain SELECT productid  FROM product  WHERE productid=ROUND(RAND()*(SELECT MAX(productid) FROM product));
+----+-------------+---------+------------+-------+---------------+--------------+---------+------+-------+----------+------------------------------+
| id | select_type | table   | partitions | type  | possible_keys | key          | key_len | ref  | rows  | filtered | Extra                        |
+----+-------------+---------+------------+-------+---------------+--------------+---------+------+-------+----------+------------------------------+
|  1 | PRIMARY     | product | NULL       | index | NULL          | idx_prod_url | 2003    | NULL | 31197 |    10.00 | Using where; Using index     |
|  2 | SUBQUERY    | NULL    | NULL       | NULL  | NULL          | NULL         | NULL    | NULL |  NULL |     NULL | Select tables optimized away |
+----+-------------+---------+------------+-------+---------------+--------------+---------+------+-------+----------+------------------------------+

谁能解释一下这种行为?

跟进: 根据 Martin 的评论,重写了查询:

SELECT productid FROM product 
WHERE productid=(SELECT ROUND(RAND()*(SELECT MAX(productid) FROM product)));

解释:

explain SELECT productid FROM product WHERE productid=(SELECT ROUND(RAND()*(SELECT MAX(productid) FROM product)));
+----+----------------------+---------+------------+-------+---------------+--------------+---------+------+-------+----------+------------------------------+
| id | select_type          | table   | partitions | type  | possible_keys | key          | key_len | ref  | rows  | filtered | Extra                        |
+----+----------------------+---------+------------+-------+---------------+--------------+---------+------+-------+----------+------------------------------+
|  1 | PRIMARY              | product | NULL       | index | NULL          | idx_prod_url | 2003    | NULL | 31197 |   100.00 | Using where; Using index     |
|  2 | UNCACHEABLE SUBQUERY | NULL    | NULL       | NULL  | NULL          | NULL         | NULL    | NULL |  NULL |     NULL | No tables used               |
|  3 | SUBQUERY             | NULL    | NULL       | NULL  | NULL          | NULL         | NULL    | NULL |  NULL |     NULL | Select tables optimized away |
+----+----------------------+---------+------------+-------+---------------+--------------+---------+------+-------+----------+------------------------------+

但是,尽管计划发生了变化,行为仍然保持不变。

跟进2:

使用INNER JOIN,该行为消失:

SELECT a.productid  FROM product a 
INNER JOIN (SELECT ROUND(RAND()*(SELECT MAX(productid))) as productid 
   FROM product) b ON a.productid=b.productid;

解释:

explain SELECT a.productid  FROM product a INNER JOIN (SELECT ROUND(RAND()*(SELECT MAX(productid))) as productid FROM product) b ON a.productid=b.productid;
+----+--------------------+------------+------------+--------+---------------+--------------+---------+-------+-------+----------+----------------+
| id | select_type        | table      | partitions | type   | possible_keys | key          | key_len | ref   | rows  | filtered | Extra          |
+----+--------------------+------------+------------+--------+---------------+--------------+---------+-------+-------+----------+----------------+
|  1 | PRIMARY            | <derived2> | NULL       | system | NULL          | NULL         | NULL    | NULL  |     1 |   100.00 | NULL           |
|  1 | PRIMARY            | a          | NULL       | const  | PRIMARY       | PRIMARY      | 4       | const |     1 |   100.00 | Using index    |
|  2 | DERIVED            | product    | NULL       | index  | NULL          | idx_prod_url | 2003    | NULL  | 31197 |   100.00 | Using index    |
|  3 | DEPENDENT SUBQUERY | NULL       | NULL       | NULL   | NULL          | NULL         | NULL    | NULL  |  NULL |     NULL | No tables used |
+----+--------------------+------------+------------+--------+---------------+--------------+---------+-------+-------+----------+----------------+

最佳答案

试试这个:

SELECT productid 
FROM product 
ORDER BY rand() LIMIT 1;

参见MySQL Select Random Records对于其他随机选择选项。

关于mysql - MariaDB 中的奇怪行为或 RAND : Single RAND delivers more than 1 result,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49342846/

相关文章:

具有多个共享列的 MySql 索引策略

mysql - 导师、学生、类(class)数据库设计

python - 在 Python 中随机选择所有组合的子集

php - 来自文本种子的随机数

python - 如何在 sklearn 中使用 LassoLarsCV 获得可重复的分割?

java - Hibernate + MySQL - 如何获得不可猜测的生成 ID?

mysql - 从转储导入数据库失败

mysql - 从mysql表中按日期获取数据

php - 从 PHP 发布的表单中清理和构建查询的更快方法

c++ - 在矩形qt中生成随机坐标