php - WHERE 子句中的 MySQL RAND() 匹配一小组行

标签 php mysql sql random

我遇到了一个关于 MySQL 的有趣问题。当我尝试将 RAND() 函数与一些大整数相乘时,我得到的最大随机数非常小。这是我的 MySQL 查询,这应该是一个非常快的随机查询,但它返回的 ID 最大值为 36000,即使有 4600000+ 个 ID。

SET @maxID=(SELECT MAX(id) FROM property); #it's about 4600000

SELECT * FROM property
WHERE 
downloaded_at IS NULL
AND id >= FLOOR(1 + RAND() * @maxID) #this returns max +/-36000
LIMIT 100

当我将此代码移动到普通的 SELECT 查询中时,一切都很好

SELECT FLOOR(1 + RAND() * (SELECT MAX(id) FROM property))

有人可以解释一下为什么会出现这个错误吗?谢谢!

编辑

<小时/>

嗯,不知何故,当我删除 downloaded_at IS NULL 时,它会出现问题,ID 更高,但结果不再那么随机。

<小时/>

我无法使用 ORDER BY RAND(),因为表太大,查询太慢,整个服务器最终在几分钟内崩溃

<小时/>

版本是5.7.21-0ubuntu0.16.04.1

最佳答案

您的随机行选择方法有偏差...行被选择的概率与其 ID 成正比。例如,如果 10 行 id = 1 到 10,则 1 有 10% 的机会被选中,2 有 20% 的机会被选中,依此类推。

此外,您的代码选择 id 小于 ~36000 的原因很明显:行(通常)按 PK 顺序处理,并且到找到第 100 个匹配行时,查询仅处理 id 约为 36000 的行。

现在,如果您有兴趣选择 100 个随机行,则可以使用此查询:

SELECT *
FROM property
WHERE id IN (
    SELECT id
    FROM property
    WHERE downloaded_at IS NULL
    ORDER BY RAND()
    LIMIT 100
)

或者可能是这样的(粗略的轮廓):

SELECT *
FROM property
WHERE id IN (
    SELECT id
    FROM property
    WHERE RAND() <= 100.0 / @maxID -- explanation below
    LIMIT 100
)

上面不涉及排序,但还是需要扫描所有的id。 100.0 与所需的行数相同,但添加更多行数以确保确定。这应该会导致每一行被选择的概率相等。

关于php - WHERE 子句中的 MySQL RAND() 匹配一小组行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48687263/

相关文章:

php - undefined variable 当值为空时

php - PHP 和 MYSQL DATE 变量中的月份和日期值可以为 0 或 null 吗?

mysql - go-gorm mysql "unsupported type []string, a slice of string"

php - friend 建议或二级相关(linkedin)算法是如何工作的

mysql - 是否可以动态地将 SET 值添加到表中?

sql - 使用 SQL 逐字反转字符串

php - CakePHP 1.3 - where 子句中的未知列

php - SQL 加入收藏夹列表返回错误的名称

php - 我在 php 中遇到错误

MySQL 不返回具有 Left Join 和 Group By 的 0 聚合行