仅使用select生成随机列表

时间:2017-02-20 10:45:41

标签: sql oracle

我有以下代码:

create table test 
(
  name varchar2(20 byte) 
);

insert into test values ('Fred');
insert into test values ('Wilma');
insert into test values ('Betty');
insert into test values ('Barny');

commit;

select * from test order by dbms_random.random;

当然,select语句将创建一个随机列表,在这种情况下恰好有4个条目。有没有办法更改select语句,以便列表可以扩展到多于或少于4个条目而无需使用PL?

1 个答案:

答案 0 :(得分:2)

您可以使用自交叉连接来平方可用行数,随机排序结果,并获取前X行;假设X低于行数的平方,例如有四个源行,交叉连接有16个结果,在这个例子中X为10,你得到你想要的:

select * from (
  select t1.name from test t1
  cross join test t2
  order by dbms_random.value
)
where rownum <= 10;

NAME                
--------------------
Betty
Betty
Fred
Betty
Wilma
Betty
Fred
Wilma
Barny
Barny

10 rows selected. 

您可以使用分层查询执行相同的操作来生成额外的行:

select * from (
  select * from test
  connect by level < 3
  order by dbms_random.value
)
where rownum <= 10;

NAME                
--------------------
Fred
Fred
Barny
Wilma
Betty
Betty
Wilma
Betty
Wilma
Wilma

10 rows selected. 

每次运行查询时,10(X)行都不同。

如果X较大,则可以增加级别数。使用level < 3,内部查询生成20行;与level < 4你得到84等等

如果你的源表很大,你可能希望限制更多,例如:添加prior子句,因此行数(以及所需的内存量)不会失控。从您的简化示例中,您很难准确猜出您需要哪些限制。例如,您可以假设&#39; name&#39;实际上是一个独特的键,做类似的事情:

select * from (
  select * from test
  connect by level < 10
  and prior name = name
  and prior dbms_random.value is not null
  order by dbms_random.value
)
where rownum <= 10;

内部查询现在只获得36行level < 10限制。您需要使用实际数据量进行测试,并调整以获得合理的结果和性能。