我如何才能最好地编写一个查询,从总共600k中随机选择10行?
当前回答
这非常快,而且是100%随机的,即使你有间隙。
将SELECT Count(*)中可用的行数计算为rows FROM TABLE 选择10个不同的随机数a_1,a_2,…,a_10在0到x之间 SELECT * FROM TABLE LIMIT 1 offset a_i for i=1,…,10
我在Bill Karwin的《SQL反模式》一书中发现了这个破解方法。
其他回答
我是这样做的:
select *
from table_with_600k_rows
where rand() < 10/600000
limit 10
我喜欢它,因为它不需要其他表,写起来很简单,执行起来非常快。
我想这是最好的办法了。
SELECT id, id * RAND( ) AS random_no, first_name, last_name
FROM user
ORDER BY random_no
我使用了Riedsio发布的http://jan.kneschke.de/projects/mysql/order-by-rand/(我使用了返回一个或多个随机值的存储过程的情况):
DROP TEMPORARY TABLE IF EXISTS rands;
CREATE TEMPORARY TABLE rands ( rand_id INT );
loop_me: LOOP
IF cnt < 1 THEN
LEAVE loop_me;
END IF;
INSERT INTO rands
SELECT r1.id
FROM random AS r1 JOIN
(SELECT (RAND() *
(SELECT MAX(id)
FROM random)) AS id)
AS r2
WHERE r1.id >= r2.id
ORDER BY r1.id ASC
LIMIT 1;
SET cnt = cnt - 1;
END LOOP loop_me;
在这篇文章中,他通过维护一个表(使用触发器等)解决了id中的间隙导致不那么随机的结果的问题。参见文章); 我通过向表中添加另一列来解决这个问题,用连续的数字填充,从1开始(编辑:此列添加到运行时由子查询创建的临时表中,不影响永久表):
DROP TEMPORARY TABLE IF EXISTS rands;
CREATE TEMPORARY TABLE rands ( rand_id INT );
loop_me: LOOP
IF cnt < 1 THEN
LEAVE loop_me;
END IF;
SET @no_gaps_id := 0;
INSERT INTO rands
SELECT r1.id
FROM (SELECT id, @no_gaps_id := @no_gaps_id + 1 AS no_gaps_id FROM random) AS r1 JOIN
(SELECT (RAND() *
(SELECT COUNT(*)
FROM random)) AS id)
AS r2
WHERE r1.no_gaps_id >= r2.id
ORDER BY r1.no_gaps_id ASC
LIMIT 1;
SET cnt = cnt - 1;
END LOOP loop_me;
在文章中,我可以看到他花了很大的精力来优化代码;我不知道我的改变是否/有多大影响性能,但对我来说非常好。
使用下面的简单查询从表中获取随机数据。
SELECT user_firstname ,
COUNT(DISTINCT usr_fk_id) cnt
FROM userdetails
GROUP BY usr_fk_id
ORDER BY cnt ASC
LIMIT 10
简单的查询,具有出色的性能和工作的差距:
SELECT * FROM tbl AS t1 JOIN (SELECT id FROM tbl ORDER BY RAND() LIMIT 10) as t2 ON t1.id=t2.id
在一个200K表上的这个查询需要0.08秒,而在我的机器上,正常版本(SELECT * FROM tbl ORDER BY RAND() LIMIT 10)需要0.35秒。
这是快速的,因为排序阶段只使用索引ID列。你可以在解释中看到这种行为:
SELECT * FROM tbl ORDER BY RAND() LIMIT 10:
SELECT * FROM tbl AS t1 JOIN (SELECT id FROM tbl ORDER BY RAND() LIMIT 10) AS t2 ON t1.id=t2.id
加权版:https://stackoverflow.com/a/41577458/893432
推荐文章
- 修改表:如何将“允许空”属性从不空改为允许空
- 比较两个SQL Server数据库(模式和数据)的最佳工具是什么?
- 在SQL中,如何在范围中“分组”?
- 选项(RECOMPILE)总是更快;为什么?
- 设置数据库从单用户模式到多用户
- oracle中的RANK()和DENSE_RANK()函数有什么区别?
- 警告用户/local/mysql/data目录不属于mysql用户
- 的类型不能用作索引中的键列
- SQL逻辑运算符优先级:And和Or
- 如何检查一个表是否存在于给定的模式中
- 添加一个复合主键
- 如何在SQL Server Management Studio中查看查询历史
- 无法添加或更新子行:外键约束失败
- 生成具有给定(数值)分布的随机数
- 如何从本地机器mysqldump远程数据库