2017-02-20 4 views
0

У меня есть следующий код:Генерация случайного списка только с помощью выбора

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; 

Конечно, оператор выбора будет создавать случайный список ровно с 4 записей в этом случае. Есть ли способ изменить оператор select, чтобы список можно было расширить до более чем 4 записей без необходимости использования PL?

+0

Вы хотите выбрать X случайный ряд из таблицы теста? –

+0

Да - извлечение X строк, содержащих случайные строки из теста таблицы –

+1

'select t. * From test t, (выберите rownum rn из двойного соединения по уровню <= 2) a order by dbms_random.random;' Генерирует 8 строк (число строки = 4 * level2 = 8). – JSapkota

ответ

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 и т. д.

Если ваша исходная таблица велика, вы можете захотеть быть более ограничительной, например. add prior, поэтому количество строк (и объем требуемой памяти) не выходит из-под контроля. Из вашего упрощенного примера трудно точно определить, какие ограничения вам понадобятся. Вы могли бы, например, и предполагая, «имя» на самом деле является уникальным ключом, сделать что-то вроде:

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 ограничением. Вам нужно будет протестировать реальные объемы данных и настроить их на разумные результаты и производительность.