MySQL使用RAND生成随机ID查询数据有时无返回结果如何解决
问题根因
- 核心问题是MySQL的
RAND()函数的计算逻辑:每扫描一行数据,都会重新执行一次RAND()计算生成新的随机值,而非你预想的预先计算出3个固定的随机ID再匹配。 - 你写的IN子句里的3个
FLOOR(RAND() * @COUNT)+1会随着每行扫描反复生成新值,绝大部分情况下不会有行的ID刚好匹配当前行计算出的三个随机数,所以会出现随机返回空结果的问题。
解决方案
方案1:小表场景(万条数据以内),直接用内置随机排序
写法最简单,无需考虑ID连续性问题:
SELECT name FROM username_generator ORDER BY RAND() LIMIT 3;
注意:该方案会对全表做排序,数据量超过10万条时性能会明显下降。
方案2:大表场景,预生成固定随机ID匹配
提前把随机ID存入变量,变量值不会随行扫描变化,避免反复计算随机数:
-- 统计总行数 SELECT COUNT(id) INTO @count FROM username_generator; -- 预生成3个固定随机ID SET @id1 = FLOOR(RAND() * @count) + 1; SET @id2 = FLOOR(RAND() * @count) + 1; SET @id3 = FLOOR(RAND() * @count) + 1; -- 匹配查询 SELECT name FROM username_generator WHERE id IN (@id1, @id2, @id3);
注意:如果你的ID存在删除导致的断层,可能出现返回结果少于3条的情况,适合ID连续的表使用。
方案3:兼容ID断层的大表方案
用随机偏移量取数,不依赖ID连续性:
SELECT name FROM username_generator LIMIT FLOOR(RAND() * (SELECT COUNT(*) FROM username_generator)), 1 UNION ALL SELECT name FROM username_generator LIMIT FLOOR(RAND() * (SELECT COUNT(*) FROM username_generator)), 1 UNION ALL SELECT name FROM username_generator LIMIT FLOOR(RAND() * (SELECT COUNT(*) FROM username_generator)), 1;
如果需要返回的3个用户名完全不重复,把
UNION ALL改成UNION即可。
内容的提问来源于stack exchange,提问作者Nik
相关产品推荐
相关产品推荐

