Necesito seleccionar filas al azar de una base de datos de Oracle.
Ej .: Supongamos una tabla con 100 filas, cómo puedo devolver aleatoriamente 20 de esos registros de las 100 filas completas.
SELECT *
FROM (
SELECT *
FROM table
ORDER BY DBMS_RANDOM.RANDOM)
WHERE rownum < 21;
No se garantiza que SAMPLE () le proporcione exactamente 20 filas, pero podría ser adecuado (y puede funcionar significativamente mejor que una consulta completa + clasificación aleatoria para tablas grandes):
SELECT * FROM table SAMPLE(20);
Nota:
20
aquí es un porcentaje aproximado, no el número de filas deseadas. En este caso, dado que tiene 100 filas, para obtener aproximadamente 20 filas solicita una muestra del 20%.fuente
SELECT * FROM table SAMPLE(10) WHERE ROWNUM <= 20;
Esto es más eficiente ya que no necesita ordenar la tabla.
fuente
SELECT column FROM ( SELECT column, dbms_random.value FROM table ORDER BY 2 ) where rownum <= 20;
fuente
Para seleccionar 20 filas al azar, creo que sería mejor seleccionar todas las filas ordenadas al azar y seleccionar las primeras 20 de ese conjunto.
Algo como:
Select * from (select * from table order by dbms_random.value) -- you can also use DBMS_RANDOM.RANDOM where rownum < 21;
Se utiliza mejor para tablas pequeñas para evitar seleccionar grandes cantidades de datos solo para descartar la mayor parte de ellos.
fuente
En resumen, se introdujeron dos formas
La primera forma tiene la ventaja de 'CORRECCIÓN', lo que significa que nunca fallará en la obtención de resultados si realmente existe, mientras que en la segunda forma puede que no obtenga ningún resultado aunque tenga casos que satisfagan la condición de consulta, ya que la información se reduce durante el muestreo.
La segunda forma tiene la ventaja de "EFICIENTE", lo que significa que obtendrá resultados más rápido y le dará una carga ligera a su base de datos. Recibí una advertencia del DBA de que mi consulta usando la primera forma da cargas a la base de datos
¡Puede elegir una de dos formas según su interés!
fuente
En el caso de tablas grandes, la forma estándar de ordenar por dbms_random.value no es efectiva porque necesita escanear la tabla completa y dbms_random.value es una función bastante lenta y requiere cambios de contexto. Para tales casos, existen 3 métodos adicionales:
1:
sample
cláusula de uso :por ejemplo:
select * from s1 sample block(1) order by dbms_random.value fetch first 1 rows only
es decir, obtenga el 1% de todos los bloques, luego ordénelos al azar y devuelva solo 1 fila.
2: si tiene un índice / clave principal en la columna con distribución normal , puede obtener valores mínimos y máximos, obtener un valor aleatorio en este rango y obtener la primera fila con un valor mayor o igual que ese valor generado aleatoriamente.
Ejemplo:
--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: obtenga un bloque de tabla aleatorio, genere rowid y obtenga una fila de la tabla por este 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 ) );
fuente
A continuación, se explica cómo elegir una muestra aleatoria de cada grupo:
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;
No estoy seguro de cuán eficiente es, pero si tiene muchas categorías y subcategorías, esto parece funcionar bien.
fuente
mesa
Tenemos mesa de profesores
Sintaxis de Oracle
SELECT * FROM ( SELECT column_name FROM table_name ORDER BY dbms_random.value ) WHERE rownum = 1;
Para una mejor comprensión, siga la captura de pantalla
fuente