如何在SQL中使用高效的简单随机样本?有问题的数据库正在运行MySQL; 我的表至少有200,000行,我想要一个大约10,000的简单随机样本.
"明显"的答案是:
SELECT * FROM table ORDER BY RAND() LIMIT 10000
Run Code Online (Sandbox Code Playgroud)
对于大型表来说,这太慢了:它为每一行调用RAND()(已经将它放在O(n)处)并对它们进行排序,最多使它成为O(n lg n).有没有办法比O(n)更快地做到这一点?
注意:正如Andrew Mao在评论中指出的那样,如果您在SQL Server上使用此方法,则应使用T-SQL函数NEWID(),因为RAND()可能会为所有行返回相同的值.
编辑:5年后
我用更大的表再次遇到了这个问题,并最终使用了@ ignorant的解决方案,并进行了两次调整:
要获取表的1000项样本,我计算行并使用frozen_rand列将结果平均下降到10,000行:
SELECT COUNT(*) FROM table; -- Use this to determine rand_low and rand_high
SELECT *
FROM table
WHERE frozen_rand BETWEEN %(rand_low)s AND %(rand_high)s
ORDER BY RAND() LIMIT 1000
Run Code Online (Sandbox Code Playgroud)
(我的实际实现涉及更多的工作,以确保我没有欠采样,并手动包裹rand_high,但基本的想法是"随机削减你的N到几千.")
虽然这会做出一些牺牲,但它允许我使用索引扫描对数据库进行采样,直到它再次小到ORDER BY RAND()为止.
我有一个查询
select id, item, producer from table
Run Code Online (Sandbox Code Playgroud)
结果是这样的:
id item producer
1 apple A
2 pear A
3 peach A
4 orange B
5 strawberry B
6 melon B
Run Code Online (Sandbox Code Playgroud)
我想要将这个结果洗牌(按ID DESC排序)并获得类似的结果
item producer
strawberry B
pear A
orange B
apple A
peach A
melon B
Run Code Online (Sandbox Code Playgroud)
我不想这样显示:
所有项目
所有B项目
所有C项目......