Yo solía hacer siempre esto en php después de resultados de consulta de SQL ... esto es probablemente mucho más rápido a la transformación, por límite de 1 apéndice de la solución
-1 para confiar order by rand()o equivalentes en todos los dbs: |. También mencionado aquí .
AD7six
20
Hace diez años un tipo dijo que el uso ORDER BY RAND()está mal ...
trejder
ORDER BY NEWID () parece ser notablemente más lento en SQL Server. Mi consulta se ve así: seleccione los mejores 1000 C.CustomerId, CL.LoginName de Customer C internal join LinkedAccount LA en C.CustomerId = LA.CustomerId internal join CustomerLogin CL en C.CustomerId = CL.CustomerId group por C.CustomerId, CL. LoginName con conteo (*)> 1 pedido por NEWID () Al eliminar la línea "ordenar por NEWID ()" se obtienen resultados mucho más rápidos.
Ben Power
3
Para SQLite use la función RANDOM ().
Slam
10
Estas soluciones no escalan. Están O(n)con nser el número de registros en la tabla. Imagina que tienes 1 millón de registros, ¿realmente quieres generar 1 millón de números aleatorios o identificadores únicos? Prefiero usar COUNT()e involucrar eso en una nueva LIMITexpresión con un solo número aleatorio.
Christian Hujer
174
Soluciones como Jeremies:
SELECT*FROMtableORDERBY RAND() LIMIT 1
funcionan, pero necesitan un escaneo secuencial de toda la tabla (porque el valor aleatorio asociado con cada fila debe calcularse, de modo que se pueda determinar el más pequeño), que puede ser bastante lento incluso para tablas de tamaño mediano. Mi recomendación sería utilizar algún tipo de columna numérica indexada (muchas tablas tienen estas como sus claves principales), y luego escribir algo como:
SELECT*FROMtableWHERE num_value >= RAND()*(SELECT MAX (num_value )FROMtable)ORDERBY num_value LIMIT 1
Esto funciona en tiempo logarítmico, independientemente del tamaño de la tabla, si num_valueestá indexado. Una advertencia: esto supone que num_valuese distribuye equitativamente en el rango 0..MAX(num_value). Si su conjunto de datos se desvía fuertemente de esta suposición, obtendrá resultados asimétricos (algunas filas aparecerán con más frecuencia que otras).
La segunda sugerencia no es al azar. No puede predecir la fila que se elegirá, pero si tuviera que apostar, apostaría en la segunda fila. Y nunca apostaría en la última fila, es menos probable que se elija cualquiera sea la distribución de su num_value y el tamaño de su mesa.
Etienne Racine
1
Sé que, por lo general, las funciones RAND () no son de muy alta calidad, pero aparte de eso, ¿podría explicar por qué la selección no sería aleatoria?
Grey Panther
13
El primero es INCORRECTO en SQL Server. La función RAND () se invoca solo una vez por consulta, no una vez por fila. Por lo tanto, siempre selecciona la primera fila (pruébalo).
Jeff Walker Code Ranger
3
El segundo también supone que se tienen en cuenta todas las filas: es posible que elija una fila que se haya eliminado.
Sam Rueby
3
@ Sam.Rueby En realidad, num_value> = RAND () ... el límite 1 asegura que las filas vacías se omitirán hasta que encuentre una fila existente.
ghord
62
No sé qué tan eficiente es esto, pero lo he usado antes:
SELECTTOP1*FROM MyTable ORDERBY newid()
Debido a que los GUID son bastante aleatorios, el orden significa que obtienes una fila aleatoria.
Estoy usando el servidor MS SQL, SELECCIONE EL TOP 1 * DE some_table_name ORDER BY NEWID () funcionó muy bien para mí, ¡gracias por los consejos chicos!
Eso es exactamente lo mismo queORDER BY RAND() LIMIT 1
Ken Bloom, el
66
Esto también es muy específico de la base de datos ya que usa TOP 1y newid().
Gris
12
Esta es una mala idea. Este método no usará un índice a menos que cada columna se indexe individualmente. La tabla con 100 millones de registros podría tomar mucho tiempo para obtener un registro.
Cambie el
1
@Switch y ¿qué solución propondrías?
Akmal Salikhov
31
ORDERBY NEWID()
toma 7.4 milliseconds
WHERE num_value >= RAND()*(SELECT MAX(num_value)FROMtable)
La segunda opción no elegirá la última fila. No sé por qué, solo señalándolo.
Voldemort
77
@Voldemort: rand()devuelve un número de punto flotante ndonde 0 < n < 1. Suponiendo que num_valuees un entero, el valor de retorno de rand() * max(num_value)también se convertirá en un entero, lo que truncará cualquier cosa después del punto decimal. Por lo tanto, rand() * max(num_value)será siempre ser inferior max(num_value), por lo que no se seleccionará la última fila.
Ian Kemp
No seré eficiente si mis datos se eliminan con frecuencia; si encuentro un vacío, tendré que volver a ejecutar toda la consulta.
Loic Coenen
1
@IanKemp Pregunta estúpida, entonces ¿por qué no simplemente usar SELECT MAX (num_value) + 1 ?? Como rand (o RANDOM en la mayoría de los casos) devuelve [0,1), obtendrá el rango completo de valores. Además, sí, tienes razón, tengo que arreglar una consulta.
tekHedd
13
No dijiste qué servidor estás usando. En versiones anteriores de SQL Server, puede usar esto:
selecttop1*from mytable orderby newid()
En SQL Server 2005 y versiones posteriores, puede usar TABLESAMPLEpara obtener una muestra aleatoria que se pueda repetir:
SELECT FirstName, LastName
FROM Contact
TABLESAMPLE (1ROWS);
@ Andrew Hedges: ORDENAR POR NEWID () es demasiado costoso
Andrei Rînea
10
Para SQL Server
newid () / order by funcionará, pero será muy costoso para grandes conjuntos de resultados porque tiene que generar una identificación para cada fila y luego ordenarlos.
TABLESAMPLE () es bueno desde el punto de vista del rendimiento, pero obtendrá una agrupación de resultados (se devolverán todas las filas de una página).
Si realmente desea una muestra aleatoria de filas individuales, modifique su consulta para filtrar las filas al azar, en lugar de usar TABLESAMPLE. Por ejemplo, la siguiente consulta usa la función NEWID para devolver aproximadamente el uno por ciento de las filas de la tabla Sales.SalesOrderDetail:
La columna SalesOrderID se incluye en la expresión CHECKSUM para que NEWID () se evalúe una vez por fila para lograr el muestreo por fila. La expresión CAST (CHECKSUM (NEWID (), SalesOrderID) y 0x7fffffff AS float / CAST (0x7fffffff AS int) se evalúa como un valor flotante aleatorio entre 0 y 1.
Cuando se ejecuta contra una tabla con 1,000,000 de filas, aquí están mis resultados:
SETSTATISTICS TIME ONSETSTATISTICS IO ON/* newid()
rows returned: 10000
logical reads: 3359
CPU time: 3312 ms
elapsed time = 3359 ms
*/SELECTTOP1PERCENT Number
FROM Numbers
ORDERBY newid()/* TABLESAMPLE
rows returned: 9269 (varies)
logical reads: 32
CPU time: 0 ms
elapsed time: 5 ms
*/SELECT Number
FROM Numbers
TABLESAMPLE (1PERCENT)/* Filter
rows returned: 9994 (varies)
logical reads: 3359
CPU time: 641 ms
elapsed time: 627 ms
*/SELECT Number
FROM Numbers
WHERE0.01>= CAST(CHECKSUM(NEWID(), Number)&0x7fffffffAS float)/ CAST (0x7fffffffAS int)SETSTATISTICS IO OFFSETSTATISTICS TIME OFF
Si puede salirse con la suya usando TABLESAMPLE, obtendrá el mejor rendimiento. De lo contrario, use el método newid () / filter. newid () / order by debería ser el último recurso si tiene un gran conjunto de resultados.
Si es posible, use declaraciones almacenadas para evitar la ineficiencia de ambos índices en RND () y crear un campo de número de registro.
PREPARE RandomRecord FROM "SELECT * FROM table LIMIT?, 1";
SET @ n = FLOOR (RAND () * (SELECCIONE EL CONTEO (*) DE la tabla));
EJECUTAR RandomRecord USANDO @n;
Esta solución también se encarga de devolver filas aleatorias cuando el valor numérico indexado utilizado en la cláusula where anterior no se distribuye por igual; así que incluso si toma casi el mismo tiempo (constante) que usar where id_value> = RAND () * MAX (id_value), es mejor.
guido
Por lo que puedo decir, esto no se ejecuta en tiempo constante, se ejecuta en tiempo lineal. En el peor de los casos, @n es igual al número de filas en la tabla y "SELECT * FROM table LIMIT?, 1" evalúa @n - 1 filas hasta llegar a la última.
Andres Riofrio
3
La mejor manera es poner un valor aleatorio en una nueva columna solo para ese propósito, y usar algo como esto (código pseude + SQL):
randomNo = random()
execSql("SELECT TOP 1 * FROM MyTable WHERE MyTable.Randomness > $randomNo")
Esta es la solución empleada por el código MediaWiki. Por supuesto, hay un sesgo en contra de los valores más pequeños, pero descubrieron que era suficiente ajustar el valor aleatorio a cero cuando no se obtienen filas.
La solución newid () puede requerir un escaneo completo de la tabla para que a cada fila se le pueda asignar un nuevo guid, que tendrá mucho menos rendimiento.
La solución rand () puede no funcionar en absoluto (es decir, con MSSQL) porque la función se evaluará solo una vez, y a cada fila se le asignará el mismo número "aleatorio".
Cuando se obtiene 0 resultados, se obtiene una muestra aleatoria demostrable (no solo "lo suficientemente buena"). Esta solución casi se escala a consultas de varias filas (piense en "mezcla aleatoria"). El problema es que los resultados tienden a seleccionarse en los mismos grupos repetidamente. Para evitar esto, necesitaría redistribuir los números aleatorios que acaba de usar. Puede hacer trampa haciendo un seguimiento de randomNo y configurándolo en max (aleatoriedad) de los resultados, pero luego p (fila i en la consulta 1 Y fila i en la consulta 2) == 0, lo cual no es justo. Déjame hacer algunos cálculos, y te responderé con un esquema verdaderamente justo.
alsuren
3
Para SQL Server 2005 y 2008, si queremos una muestra aleatoria de filas individuales (de Books Online ):
SELECT ID FROMTABLEWHERE ID >= My_Generated_Random ORDERBY ID LIMIT 1
Tenga en cuenta que comprobará si hay filas cuyos ID sean IGUALES o SUPERIORES al valor elegido. También es posible buscar la fila hacia abajo en la tabla y obtener una ID igual o inferior que My_Generated_Random, luego modificar la consulta de esta manera:
SELECT ID FROMTABLEWHERE ID <= My_Generated_Random ORDERBY ID DESC LIMIT 1
¿Qué pasaría si la ID aleatoria generada ya no existe en la tabla? Las filas eliminadas o pasivas que no desea mostrar al usuario podrían causar problemas.
Ebleme
Nada. Obtiene el número de identificación MÁS CERCANO, no exacto. Si considera que id = 1 se eliminará, intercambie 1 con un mínimo.
forsberg
2
Como se señaló en el comentario de @ BillKarwin sobre la respuesta de @ cnu ...
Al combinar con un LIMIT, descubrí que funciona mucho mejor (al menos con PostgreSQL 9.1) para UNIRSE con un orden aleatorio en lugar de ordenar directamente las filas reales: por ejemplo
SELECT*FROM tbl_post AS t
JOIN...JOIN(SELECT id, CAST(-2147483648* RANDOM()AS integer)AS rand
FROM tbl_post
WHERE create_time >=1349928000) r ON r.id = t.id
WHERE create_time >=1349928000AND...ORDERBY r.rand
LIMIT 100
Solo asegúrese de que la 'r' genere un valor 'rand' para cada valor clave posible en la consulta compleja que se une con ella, pero aún limite el número de filas de 'r' cuando sea posible.
CAST as Integer es especialmente útil para PostgreSQL 9.2 que tiene una optimización de clasificación específica para tipos flotantes de precisión entera y única.
La mayoría de las soluciones aquí apuntan a evitar la clasificación, pero aún necesitan hacer un escaneo secuencial sobre una tabla.
También hay una manera de evitar el escaneo secuencial cambiando al escaneo de índice. Si conoce el valor del índice de su fila aleatoria, puede obtener el resultado casi de forma instantánea. El problema es cómo adivinar un valor de índice.
La siguiente solución funciona en PostgreSQL 8.4:
explain analyze select*from cms_refs where rec_id in(select(random()*(select last_value from cms_refs_rec_id_seq))::bigint
from generate_series(1,10))
limit 1;
En la solución anterior, adivina 10 diferentes valores de índice aleatorio del rango 0 .. [último valor de id].
El número 10 es arbitrario: puede usar 100 o 1000 ya que (sorprendentemente) no tiene un gran impacto en el tiempo de respuesta.
También hay un problema: si tiene identificadores escasos , puede pasar por alto . La solución es tener un plan de respaldo :) En este caso, un orden antiguo puro por consulta aleatoria (). Cuando la identificación combinada se ve así:
explain analyze select*from cms_refs where rec_id in(select(random()*(select last_value from cms_refs_rec_id_seq))::bigint
from generate_series(1,10))unionall(select*from cms_refs orderby random() limit 1)
limit 1;
No es la unión TODA cláusula. En este caso, si la primera parte devuelve datos, la segunda NUNCA se ejecuta.
Últimamente, pero llegué aquí a través de Google, por lo que, en aras de la posteridad, agregaré una solución alternativa.
Otro enfoque es usar TOP dos veces, con órdenes alternas. No sé si es "SQL puro", porque usa una variable en el TOP, pero funciona en SQL Server 2008. Aquí hay un ejemplo que uso en una tabla de palabras del diccionario, si quiero una palabra al azar.
SELECTTOP1
word
FROM(SELECTTOP(@idx)
word
FROM
dbo.DictionaryAbridged WITH(NOLOCK)ORDERBY
word DESC)AS D
ORDERBY
word ASC
Por supuesto, @idx es un número entero generado aleatoriamente que varía de 1 a COUNT (*) en la tabla de destino, inclusive. Si su columna está indexada, también se beneficiará de ella. Otra ventaja es que puede usarlo en una función, ya que NEWID () no está permitido.
Por último, la consulta anterior se ejecuta en aproximadamente 1/10 del tiempo de ejecución de un tipo de consulta NEWID () en la misma tabla. YYMV
Después de probar muchas de las respuestas, creo que esta es la mejor. Parece ser rápido y elige un buen número aleatorio cada vez. Parece similar a la segunda sugerencia de @GreyPanther anterior, pero esta respuesta elige más números aleatorios.
Jeff Baker,
1
Todavía no vi esta variación en las respuestas. Tenía una restricción adicional donde necesitaba, dada una semilla inicial, para seleccionar el mismo conjunto de filas cada vez.
NewId()es insignificantemente más lento que rand(checksum(*)), por lo que es posible que no desee utilizarlo contra grandes conjuntos de registros.
Selección con semilla inicial:
declare@seed int
set@seed = Year(getdate())* month(getdate())/* any other initial seed here */selecttop10percent*from table_name
orderby rand(checksum(*)% seed)/* any other math function here */
Si necesita seleccionar el mismo conjunto dado una semilla, esto parece funcionar.
En SQL Server puede combinar TABLESAMPLE con NEWID () para obtener una aleatoriedad bastante buena y aún así tener velocidad. Esto es especialmente útil si realmente solo desea 1 o un pequeño número de filas.
Con SQL Server 2012+ puede usar la consulta OFFSET FETCH para hacer esto para una sola fila aleatoria
select*from MyTable ORDERBY id OFFSET n ROWFETCH NEXT 1ROWS ONLY
donde id es una columna de identidad y n es la fila que desea, calculada como un número aleatorio entre 0 y count () - 1 de la tabla (el desplazamiento 0 es la primera fila después de todo)
Esto funciona con agujeros en los datos de la tabla, siempre que tenga un índice para trabajar para la cláusula ORDER BY. También es muy bueno para la aleatoriedad, ya que te esfuerzas para pasar, pero los inconvenientes en otros métodos no están presentes. Además, el rendimiento es bastante bueno, en un conjunto de datos más pequeño se mantiene bien, aunque no he probado pruebas de rendimiento serias en varios millones de filas.
Hace diez años (2005), un tipo dijo que usar ORDER BY RAND()está mal ...
trejder
0
Tengo que estar de acuerdo con CD-MaN: Usar "ORDER BY RAND ()" funcionará bien para tablas pequeñas o cuando haga su SELECCIÓN solo unas pocas veces.
También uso la técnica "num_value> = RAND () * ...", y si realmente quiero tener resultados aleatorios, tengo una columna especial "aleatoria" en la tabla que actualizo una vez al día más o menos. Esa única ejecución de ACTUALIZACIÓN llevará algún tiempo (especialmente porque tendrá que tener un índice en esa columna), pero es mucho más rápido que crear números aleatorios para cada fila cada vez que se ejecuta la selección.
Tenga cuidado porque TableSample en realidad no devuelve una muestra aleatoria de filas. Dirige su consulta para mirar una muestra aleatoria de las páginas de 8 KB que forman su fila. Luego, su consulta se ejecuta contra los datos contenidos en estas páginas. Debido a cómo se pueden agrupar los datos en estas páginas (orden de inserción, etc.), esto podría generar datos que en realidad no son una muestra aleatoria.
Parece que muchas de las ideas enumeradas todavía usan el orden
Sin embargo, si usa una tabla temporal, puede asignar un índice aleatorio (como lo han sugerido muchas de las soluciones), y luego tomar la primera que sea mayor que un número arbitrario entre 0 y 1.
Por ejemplo (para DB2):
WITH TEMP AS(SELECT COMLUMN, RAND()AS IDX FROMTABLE)SELECTCOLUMNFROMTABLEWHERE IDX >.5FETCH FIRST 1ROW ONLY
Después de considerar esta solución, he encontrado una falla fundamental en mi lógica. Esto devolvería consistentemente los mismos valores de configuración pequeños, cerca del comienzo de la tabla, porque supongo que si hubo una distribución uniforme entre 0 y 1, existe una probabilidad del 50% de que la primera fila cumpla con ese criterio.
Hay una mejor solución para Oracle en lugar de usar dbms_random.value, mientras que requiere un escaneo completo para ordenar filas por dbms_random.value y es bastante lento para tablas grandes.
Para SQL Server 2005 y superior, extender la respuesta de @ GreyPanther para los casos en que num_valueno tiene valores continuos. Esto también funciona para los casos en que no hemos distribuido uniformemente los conjuntos de datos y cuando num_valueno es un número sino un identificador único.
WITH CTE_Table (SelRow, num_value)AS(SELECT ROW_NUMBER()OVER(ORDERBY ID)AS SelRow, num_value FROMtable)SELECT*FROMtableWhere num_value =(SELECTTOP1 num_value FROM CTE_Table WHERE SelRow >= RAND()*(SELECT MAX(SelRow)FROM CTE_Table))
Respuestas:
Vea esta publicación: SQL para seleccionar una fila aleatoria de una tabla de base de datos . Sigue los métodos para hacerlo en MySQL, PostgreSQL, Microsoft SQL Server, IBM DB2 y Oracle (lo siguiente se copia de ese enlace):
Seleccione una fila aleatoria con MySQL:
Seleccione una fila aleatoria con PostgreSQL:
Seleccione una fila aleatoria con Microsoft SQL Server:
Seleccione una fila aleatoria con IBM DB2
Seleccione un registro aleatorio con Oracle:
fuente
order by rand()
o equivalentes en todos los dbs: |. También mencionado aquí .ORDER BY RAND()
está mal ...O(n)
conn
ser el número de registros en la tabla. Imagina que tienes 1 millón de registros, ¿realmente quieres generar 1 millón de números aleatorios o identificadores únicos? Prefiero usarCOUNT()
e involucrar eso en una nuevaLIMIT
expresión con un solo número aleatorio.Soluciones como Jeremies:
funcionan, pero necesitan un escaneo secuencial de toda la tabla (porque el valor aleatorio asociado con cada fila debe calcularse, de modo que se pueda determinar el más pequeño), que puede ser bastante lento incluso para tablas de tamaño mediano. Mi recomendación sería utilizar algún tipo de columna numérica indexada (muchas tablas tienen estas como sus claves principales), y luego escribir algo como:
Esto funciona en tiempo logarítmico, independientemente del tamaño de la tabla, si
num_value
está indexado. Una advertencia: esto supone quenum_value
se distribuye equitativamente en el rango0..MAX(num_value)
. Si su conjunto de datos se desvía fuertemente de esta suposición, obtendrá resultados asimétricos (algunas filas aparecerán con más frecuencia que otras).fuente
No sé qué tan eficiente es esto, pero lo he usado antes:
Debido a que los GUID son bastante aleatorios, el orden significa que obtienes una fila aleatoria.
fuente
ORDER BY RAND() LIMIT 1
TOP 1
ynewid()
.toma
7.4 milliseconds
toma
0.0065 milliseconds
!Definitivamente iré con este último método.
fuente
rand()
devuelve un número de punto flotanten
donde0 < n < 1
. Suponiendo quenum_value
es un entero, el valor de retorno derand() * max(num_value)
también se convertirá en un entero, lo que truncará cualquier cosa después del punto decimal. Por lo tanto,rand() * max(num_value)
será siempre ser inferiormax(num_value)
, por lo que no se seleccionará la última fila.No dijiste qué servidor estás usando. En versiones anteriores de SQL Server, puede usar esto:
En SQL Server 2005 y versiones posteriores, puede usar
TABLESAMPLE
para obtener una muestra aleatoria que se pueda repetir:fuente
Para SQL Server
newid () / order by funcionará, pero será muy costoso para grandes conjuntos de resultados porque tiene que generar una identificación para cada fila y luego ordenarlos.
TABLESAMPLE () es bueno desde el punto de vista del rendimiento, pero obtendrá una agrupación de resultados (se devolverán todas las filas de una página).
Para obtener una muestra aleatoria verdadera con mejor rendimiento, la mejor manera es filtrar las filas al azar. Encontré el siguiente ejemplo de código en el artículo de los Libros en pantalla de SQL Server Limitar los conjuntos de resultados mediante TABLESAMPLE :
Cuando se ejecuta contra una tabla con 1,000,000 de filas, aquí están mis resultados:
Si puede salirse con la suya usando TABLESAMPLE, obtendrá el mejor rendimiento. De lo contrario, use el método newid () / filter. newid () / order by debería ser el último recurso si tiene un gran conjunto de resultados.
fuente
Si es posible, use declaraciones almacenadas para evitar la ineficiencia de ambos índices en RND () y crear un campo de número de registro.
fuente
La mejor manera es poner un valor aleatorio en una nueva columna solo para ese propósito, y usar algo como esto (código pseude + SQL):
Esta es la solución empleada por el código MediaWiki. Por supuesto, hay un sesgo en contra de los valores más pequeños, pero descubrieron que era suficiente ajustar el valor aleatorio a cero cuando no se obtienen filas.
La solución newid () puede requerir un escaneo completo de la tabla para que a cada fila se le pueda asignar un nuevo guid, que tendrá mucho menos rendimiento.
La solución rand () puede no funcionar en absoluto (es decir, con MSSQL) porque la función se evaluará solo una vez, y a cada fila se le asignará el mismo número "aleatorio".
fuente
Para SQL Server 2005 y 2008, si queremos una muestra aleatoria de filas individuales (de Books Online ):
fuente
En lugar de usar RAND (), como no se recomienda , simplemente puede obtener la ID máxima (= Max):
obtener un azar entre 1..Max (= My_Generated_Random)
y luego ejecuta este SQL:
Tenga en cuenta que comprobará si hay filas cuyos ID sean IGUALES o SUPERIORES al valor elegido. También es posible buscar la fila hacia abajo en la tabla y obtener una ID igual o inferior que My_Generated_Random, luego modificar la consulta de esta manera:
fuente
Como se señaló en el comentario de @ BillKarwin sobre la respuesta de @ cnu ...
Al combinar con un LIMIT, descubrí que funciona mucho mejor (al menos con PostgreSQL 9.1) para UNIRSE con un orden aleatorio en lugar de ordenar directamente las filas reales: por ejemplo
Solo asegúrese de que la 'r' genere un valor 'rand' para cada valor clave posible en la consulta compleja que se une con ella, pero aún limite el número de filas de 'r' cuando sea posible.
CAST as Integer es especialmente útil para PostgreSQL 9.2 que tiene una optimización de clasificación específica para tipos flotantes de precisión entera y única.
fuente
La mayoría de las soluciones aquí apuntan a evitar la clasificación, pero aún necesitan hacer un escaneo secuencial sobre una tabla.
También hay una manera de evitar el escaneo secuencial cambiando al escaneo de índice. Si conoce el valor del índice de su fila aleatoria, puede obtener el resultado casi de forma instantánea. El problema es cómo adivinar un valor de índice.
La siguiente solución funciona en PostgreSQL 8.4:
En la solución anterior, adivina 10 diferentes valores de índice aleatorio del rango 0 .. [último valor de id].
El número 10 es arbitrario: puede usar 100 o 1000 ya que (sorprendentemente) no tiene un gran impacto en el tiempo de respuesta.
También hay un problema: si tiene identificadores escasos , puede pasar por alto . La solución es tener un plan de respaldo :) En este caso, un orden antiguo puro por consulta aleatoria (). Cuando la identificación combinada se ve así:
No es la unión TODA cláusula. En este caso, si la primera parte devuelve datos, la segunda NUNCA se ejecuta.
fuente
Últimamente, pero llegué aquí a través de Google, por lo que, en aras de la posteridad, agregaré una solución alternativa.
Otro enfoque es usar TOP dos veces, con órdenes alternas. No sé si es "SQL puro", porque usa una variable en el TOP, pero funciona en SQL Server 2008. Aquí hay un ejemplo que uso en una tabla de palabras del diccionario, si quiero una palabra al azar.
Por supuesto, @idx es un número entero generado aleatoriamente que varía de 1 a COUNT (*) en la tabla de destino, inclusive. Si su columna está indexada, también se beneficiará de ella. Otra ventaja es que puede usarlo en una función, ya que NEWID () no está permitido.
Por último, la consulta anterior se ejecuta en aproximadamente 1/10 del tiempo de ejecución de un tipo de consulta NEWID () en la misma tabla. YYMV
fuente
También puede intentar usar la
new id()
función.Simplemente escriba su consulta y use el orden por
new id()
función. Es bastante al azar.fuente
Para que MySQL obtenga un registro aleatorio
Más detalles http://jan.kneschke.de/projects/mysql/order-by-rand/
fuente
Todavía no vi esta variación en las respuestas. Tenía una restricción adicional donde necesitaba, dada una semilla inicial, para seleccionar el mismo conjunto de filas cada vez.
Para MS SQL:
Ejemplo mínimo:
Tiempo de ejecución normalizado: 1.00
Ejemplo de NewId ():
Tiempo de ejecución normalizado: 1.02
NewId()
es insignificantemente más lento querand(checksum(*))
, por lo que es posible que no desee utilizarlo contra grandes conjuntos de registros.Selección con semilla inicial:
Si necesita seleccionar el mismo conjunto dado una semilla, esto parece funcionar.
fuente
En MSSQL (probado en 11.0.5569) usando
es significativamente más rápido que
fuente
En SQL Server puede combinar TABLESAMPLE con NEWID () para obtener una aleatoriedad bastante buena y aún así tener velocidad. Esto es especialmente útil si realmente solo desea 1 o un pequeño número de filas.
fuente
Con SQL Server 2012+ puede usar la consulta OFFSET FETCH para hacer esto para una sola fila aleatoria
donde id es una columna de identidad y n es la fila que desea, calculada como un número aleatorio entre 0 y count () - 1 de la tabla (el desplazamiento 0 es la primera fila después de todo)
Esto funciona con agujeros en los datos de la tabla, siempre que tenga un índice para trabajar para la cláusula ORDER BY. También es muy bueno para la aleatoriedad, ya que te esfuerzas para pasar, pero los inconvenientes en otros métodos no están presentes. Además, el rendimiento es bastante bueno, en un conjunto de datos más pequeño se mantiene bien, aunque no he probado pruebas de rendimiento serias en varios millones de filas.
fuente
fuente
ORDER BY RAND()
está mal ...Tengo que estar de acuerdo con CD-MaN: Usar "ORDER BY RAND ()" funcionará bien para tablas pequeñas o cuando haga su SELECCIÓN solo unas pocas veces.
También uso la técnica "num_value> = RAND () * ...", y si realmente quiero tener resultados aleatorios, tengo una columna especial "aleatoria" en la tabla que actualizo una vez al día más o menos. Esa única ejecución de ACTUALIZACIÓN llevará algún tiempo (especialmente porque tendrá que tener un índice en esa columna), pero es mucho más rápido que crear números aleatorios para cada fila cada vez que se ejecuta la selección.
fuente
Tenga cuidado porque TableSample en realidad no devuelve una muestra aleatoria de filas. Dirige su consulta para mirar una muestra aleatoria de las páginas de 8 KB que forman su fila. Luego, su consulta se ejecuta contra los datos contenidos en estas páginas. Debido a cómo se pueden agrupar los datos en estas páginas (orden de inserción, etc.), esto podría generar datos que en realidad no son una muestra aleatoria.
Ver: http://www.mssqltips.com/tip.asp?tip=1308
Esta página de MSDN para TableSample incluye un ejemplo de cómo generar una muestra de datos realmente aleatoria.
http://msdn.microsoft.com/en-us/library/ms189108.aspx
fuente
Parece que muchas de las ideas enumeradas todavía usan el orden
Sin embargo, si usa una tabla temporal, puede asignar un índice aleatorio (como lo han sugerido muchas de las soluciones), y luego tomar la primera que sea mayor que un número arbitrario entre 0 y 1.
Por ejemplo (para DB2):
fuente
Una manera simple y eficiente de http://akinas.com/pages/en/blog/mysql_random_row/
fuente
Hay una mejor solución para Oracle en lugar de usar dbms_random.value, mientras que requiere un escaneo completo para ordenar filas por dbms_random.value y es bastante lento para tablas grandes.
Use esto en su lugar:
fuente
Para Firebird:
fuente
Para SQL Server 2005 y superior, extender la respuesta de @ GreyPanther para los casos en que
num_value
no tiene valores continuos. Esto también funciona para los casos en que no hemos distribuido uniformemente los conjuntos de datos y cuandonum_value
no es un número sino un identificador único.fuente
La función aleatoria del sql podría ayudar. Además, si desea limitar a una sola fila, simplemente agréguela al final.
fuente