我遇到了一个关于 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/