我如何才能最好地编写一个查询,从总共600k中随机选择10行?
当前回答
使用这个查询:
select floor(RAND() * (SELECT MAX(key) FROM table)) from table limit 10
查询时间:0.016秒
其他回答
一个伟大的职位处理几个情况,从简单,到差距,到不均匀与差距。
http://jan.kneschke.de/projects/mysql/order-by-rand/
对于大多数一般情况,你可以这样做:
SELECT name
FROM random AS r1 JOIN
(SELECT CEIL(RAND() *
(SELECT MAX(id)
FROM random)) AS id)
AS r2
WHERE r1.id >= r2.id
ORDER BY r1.id ASC
LIMIT 1
这假设id的分布是相等的,并且id列表中可能存在间隙。有关更高级的示例,请参阅本文
从书中:
使用偏移量选择随机行
这是另一种避免前面提到的问题的技术 替代方法是统计数据集中的行数并返回一个随机值 0到计数之间的数字。然后用这个数字作为抵消 查询数据集时
$rand = "SELECT ROUND(RAND() * (SELECT COUNT(*) FROM Bugs))";
$offset = $pdo->query($rand)->fetch(PDO::FETCH_ASSOC);
$sql = "SELECT * FROM Bugs LIMIT 1 OFFSET :offset";
$stmt = $pdo->prepare($sql);
$stmt->execute( $offset );
$rand_bug = $stmt->fetch();
在不能假定连续键值和时使用此解决方案 您需要确保每一行都有均等的机会被选中。
SELECT
*
FROM
table_with_600k_rows
WHERE
RAND( )
ORDER BY
id DESC
LIMIT 30;
Id是主键,按Id排序, 解释table_with_600k_rows,发现该行不扫描整个表
如果键之间没有间隙而且都是数字你可以计算随机数然后选择这些行。但事实可能并非如此。
所以一种解决方案是:
SELECT * FROM table WHERE key >= FLOOR(RAND()*MAX(id)) LIMIT 1
这将确保你在键的范围内得到一个随机数然后你选择下一个更大的最佳值。 你必须这样做10次。
然而,这并不是随机的,因为你的钥匙很可能不是均匀分布的。
这真的是一个大问题,不容易解决满足所有的要求,MySQL的rand()是最好的,如果你真的想要10个随机行。
然而,还有另一种解决方案,它速度很快,但涉及到随机性时也需要权衡,但可能更适合你。在这里阅读:我如何优化MySQL的ORDER BY RAND()函数?
问题是你需要它有多随机。
你能多解释一下吗?这样我才能给你一个好的解决办法。
例如,我合作的一家公司有一个解决方案,他们需要非常快的绝对随机性。最后,他们用随机值预填充数据库,这些随机值是从降序选择的,然后再次设置为不同的随机值。
如果你几乎没有更新,你也可以填充一个递增的id,这样你就没有间隙,只是可以在选择之前计算随机键…这取决于用例!
我需要一个查询从一个相当大的表中返回大量随机行。这是我想到的。首先获取最大记录id:
SELECT MAX(id) FROM table_name;
然后将该值代入:
SELECT * FROM table_name WHERE id > FLOOR(RAND() * max) LIMIT n;
Where max is the maximum record id in the table and n is the number of rows you want in your result set. The assumption is that there are no gaps in the record id's although I doubt it would affect the result if there were (haven't tried it though). I also created this stored procedure to be more generic; pass in the table name and number of rows to be returned. I'm running MySQL 5.5.38 on Windows 2008, 32GB, dual 3GHz E5450, and on a table with 17,361,264 rows it's fairly consistent at ~.03 sec / ~11 sec to return 1,000,000 rows. (times are from MySQL Workbench 6.1; you could also use CEIL instead of FLOOR in the 2nd select statement depending on your preference)
DELIMITER $$
USE [schema name] $$
DROP PROCEDURE IF EXISTS `random_rows` $$
CREATE PROCEDURE `random_rows`(IN tab_name VARCHAR(64), IN num_rows INT)
BEGIN
SET @t = CONCAT('SET @max=(SELECT MAX(id) FROM ',tab_name,')');
PREPARE stmt FROM @t;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @t = CONCAT(
'SELECT * FROM ',
tab_name,
' WHERE id>FLOOR(RAND()*@max) LIMIT ',
num_rows);
PREPARE stmt FROM @t;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
$$
then
CALL [schema name].random_rows([table name], n);
推荐文章
- 修改表:如何将“允许空”属性从不空改为允许空
- 比较两个SQL Server数据库(模式和数据)的最佳工具是什么?
- 在SQL中,如何在范围中“分组”?
- 选项(RECOMPILE)总是更快;为什么?
- 设置数据库从单用户模式到多用户
- oracle中的RANK()和DENSE_RANK()函数有什么区别?
- 警告用户/local/mysql/data目录不属于mysql用户
- 的类型不能用作索引中的键列
- SQL逻辑运算符优先级:And和Or
- 如何检查一个表是否存在于给定的模式中
- 添加一个复合主键
- 如何在SQL Server Management Studio中查看查询历史
- 无法添加或更新子行:外键约束失败
- 生成具有给定(数值)分布的随机数
- 如何从本地机器mysqldump远程数据库