我有以下代码:
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?
答案 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
限制。您需要使用实际数据量进行测试,并调整以获得合理的结果和性能。