Мне нужно случайным образом выбрать строки из базы данных Oracle.
Пример: предположим, что таблица со 100 строками, как я могу случайным образом вернуть 20 таких записей из всех 100 строк.
SELECT *
FROM (
SELECT *
FROM table
ORDER BY DBMS_RANDOM.RANDOM)
WHERE rownum < 21;
SAMPLE () не гарантирует получение ровно 20 строк, но может быть подходящим (и может работать значительно лучше, чем полный запрос + сортировка случайным образом для больших таблиц):
SELECT * FROM table SAMPLE(20);
Примечание:
20
это приблизительный процент, а не желаемое количество строк. В этом случае, поскольку у вас 100 строк, чтобы получить примерно 20 строк, вы запрашиваете 20% выборку.источник
SELECT * FROM table SAMPLE(10) WHERE ROWNUM <= 20;
Это более эффективно, так как не нужно сортировать таблицу.
источник
SELECT column FROM ( SELECT column, dbms_random.value FROM table ORDER BY 2 ) where rownum <= 20;
источник
Чтобы случайным образом выбрать 20 строк, я думаю, вам лучше выбрать их в случайном порядке и выбрать первые 20 из этого набора.
Что-то вроде:
Select * from (select * from table order by dbms_random.value) -- you can also use DBMS_RANDOM.RANDOM where rownum < 21;
Лучше всего использовать для небольших таблиц, чтобы не выбирать большие фрагменты данных только для того, чтобы отбросить большую их часть.
источник
Таким образом, были представлены два способа
Первый способ имеет преимущество в «ПРАВИЛЬНОСТЬ», что означает, что вы никогда не потерпите неудачу в получении результата, если он действительно существует, в то время как второй способ может не получить результата, даже если у него есть случаи, удовлетворяющие условию запроса, поскольку информация уменьшается во время выборки.
Второй способ имеет преимущество в «ЭФФЕКТИВНОСТИ», что означает, что вы получите результат быстрее и уменьшите нагрузку на базу данных. Мне было дано предупреждение от администратора базы данных, что мой запрос, использующий первый способ, загружает базу данных.
Вы можете выбрать один из двух способов по вашему желанию!
источник
В случае больших таблиц стандартный способ с сортировкой по dbms_random.value неэффективен, потому что вам нужно сканировать всю таблицу, а dbms_random.value - довольно медленная функция и требует переключения контекста. Для таких случаев есть 3 дополнительных метода:
1: Использование
sample
предложения:например:
select * from s1 sample block(1) order by dbms_random.value fetch first 1 rows only
т.е. получить 1% всех блоков, затем отсортировать их случайным образом и вернуть только 1 строку.
2: если у вас есть индекс / первичный ключ в столбце с нормальным распределением , вы можете получить минимальные и максимальные значения, получить случайное значение в этом диапазоне и получить первую строку со значением, большим или равным этому случайно сгенерированному значению.
Пример:
--big table with 1 mln rows with primary key on ID with normal distribution: Create table s1(id primary key,padding) as select level, rpad('x',100,'x') from dual connect by level<=1e6; select * from s1 where id>=(select dbms_random.value( (select min(id) from s1), (select max(id) from s1) ) from dual) order by id fetch first 1 rows only;
3: получить случайный блок таблицы, сгенерировать rowid и получить строку из таблицы по этому rowid :
select * from s1 where rowid = ( select DBMS_ROWID.ROWID_CREATE ( 1, objd, file#, block#, 1) from ( select/*+ rule */ file#,block#,objd from v$bh b where b.objd in (select o.data_object_id from user_objects o where object_name='S1' /* table_name */) order by dbms_random.value fetch first 1 rows only ) );
источник
Вот как выбрать случайную выборку из каждой группы:
SELECT GROUPING_COLUMN, MIN (COLUMN_NAME) KEEP (DENSE_RANK FIRST ORDER BY DBMS_RANDOM.VALUE) AS RANDOM_SAMPLE FROM TABLE_NAME GROUP BY GROUPING_COLUMN ORDER BY GROUPING_COLUMN;
Я не уверен, насколько это эффективно, но если у вас много категорий и подкатегорий, это, кажется, отлично справляется со своей задачей.
источник
стол
У нас есть учительский стол
Синтаксис Oracle
SELECT * FROM ( SELECT column_name FROM table_name ORDER BY dbms_random.value ) WHERE rownum = 1;
Для лучшего понимания смотрите скриншот
источник