在MySQL里可以用rand()、ORACLE里可以用dbms_random.value、MSSQL里可以用rand或newID(不是随机函数,但也可以用它达到目的).
例如:
MYSQL里随机提取USERS表里的20条记录
select * from USERS order by rand() limit 20
ORACLE里则可以写成
1.select * from USERS where rownum<=20 order by dbms_random.value
dbms_random.value(1,100) 这个表示产生随机数的范围从1到100,一般是小数点...
2.先用一个子查询找出所有符合条件的,再随机排序,在外层取top n
select * from (select object_name from all_objects order by dbms_random.random )where rownum<10;
3.用SELECT...SAMPLE(百分比)
SAMPLE是随机从表中取数据,这发生在WHERE过滤之前,也就是说你的组合条件有可能在SAMPLE中不存在,那么一条数据也取不到。可以考虑这个方法:
建一个临时表存放所有满足WHERE条件的数据,用动态SQL 做INSERT...SELECT, 根据SQL%ROWCOUNT来决定是否取SAMPLE以及SAMPLE的百分比。然后再用ROWNUM精确控制返回行数,比如:
select * from (SELECT * FROM TMP SAMPLE (0.1)) where rownum<=10;
以上是从临时表TMP随机取 0.1% 的数据,再返回前10行。
这方法好处是省略了order by dbms_random.random的开销, 但是前面的INSERT可能代价很大。这是无法避免的,你必须知道所有满足条件的数据才能从中随机选择。
如果INSERT的结果很小,那么就在临时表上用order by dbms_random.random的方法,因为SAMPLE不能保证返回确定百分比的数据。
4.新建了一个测试表Test,里面只有一个递增的字段“ID”,1万条数据。测试脚本中需把insert语句中的select子句作相应的替换
方法一,使用随机数:
1 |
select * from ( |
2 |
select * from test order by dbms_random.value |
3 |
) where rownum <= 50 |
这是最原始的方法,测试脚本执行了49分钟还没结束,手动停了。测试结果能涵盖1万条数据,命中次数最高是343次,最低是209次
优点:随机性好
缺点:性能差
方法二,使用sample函数:
1 |
select * from test sample(10) where rownum<=50; |
测试脚本11秒就执行完,但测试结果只涵盖了805条数据,并且分布非常不均匀,命中次数最高是10133次,最低只有1次
优点:性能最好
缺点:随机性最差
方法三,结合sample和随机数:
1 |
select * from ( |
2 |
select * from test sample(10) order by dbms_random.value |
3 |
) where rownum <= 50 |
先用sample抽取部分数据,再用随机数排序。测试脚本运行10分钟,测试结果涵盖1万条数据,命中次数最高589次,最低423次
优点:性能比方法一好,随机性比方法二好
缺点:因为用了sample函数,当数据量比较少时,不能保证每次都能返回50条样本数据。抽样的表不能用dblink
测试脚本
01 |
declare |
02 |
l_num number := 1; |
03 |
begin |
04 |
execute immediate 'truncate table test_result' ; |
05 |
while l_num <= 100000 loop |
06 |
insert into test_result |
07 |
(result) |
08 |
( select * |
09 |
from ( select * from test order by dbms_random.value) |
10 |
where rownum <= 50); |
11 |
if mod(l_num, 1000) = 0 then |
12 |
commit ; |
13 |
end if; |
14 |
l_num := l_num + 1; |
15 |
end loop; |
16 |
commit ; |
17 |
end ; |
MSSQL里则可以写成
select top 20 * from USERS order by newid()