Respuestas:
Una gran publicación manejando varios casos, desde simples, hasta huecos, hasta no uniformes con huecos.
http://jan.kneschke.de/projects/mysql/order-by-rand/
Para el caso más general, así es como lo hace:
SELECT name
FROM random AS r1 JOIN
(SELECT CEIL(RAND() *
(SELECT MAX(id)
FROM random)) AS id)
AS r2
WHERE r1.id >= r2.id
ORDER BY r1.id ASC
LIMIT 1
Esto supone que la distribución de identificadores es igual y que puede haber huecos en la lista de identificadores. Vea el artículo para ejemplos más avanzados.
mysqli_fetch_assoc($result)
? ¿O esos 10 resultados no son necesariamente distinguibles?
SELECT column FROM table
ORDER BY RAND()
LIMIT 10
No es la solución eficiente pero funciona
ORDER BY RAND()
es relativamente lento
SELECT words, transcription, translation, sound FROM vocabulary WHERE menu_id=$menuId ORDER BY RAND() LIMIT 10
toma 0.0010, sin LIMIT 10 tomó 0.0012 (en esa tabla 3500 palabras).
Consulta simple que tiene un excelente rendimiento y funciona con lagunas :
SELECT * FROM tbl AS t1 JOIN (SELECT id FROM tbl ORDER BY RAND() LIMIT 10) as t2 ON t1.id=t2.id
Esta consulta en una tabla de 200K toma 0.08s y la versión normal (SELECT * FROM tbl ORDER BY RAND () LIMIT 10) toma 0.35s en mi máquina.
Esto es rápido porque la fase de clasificación solo usa la columna de ID indexada. Puede ver este comportamiento en la explicación:
SELECCIONAR * DESDE tbl ORDENAR POR RAND () LÍMITE 10:
SELECT * FROM tbl AS t1 JOIN (SELECT id FROM tbl ORDER BY RAND () LIMIT 10) as t2 ON t1.id = t2.id
Versión ponderada : https://stackoverflow.com/a/41577458/893432
Recibo consultas rápidas (alrededor de 0,5 segundos) con una CPU lenta , seleccionando 10 filas aleatorias en una base de datos de MySQL de 400 K de tamaño no almacenado en caché de 2 Gb. Vea aquí mi código: Selección rápida de filas aleatorias en MySQL
<?php
$time= microtime_float();
$sql='SELECT COUNT(*) FROM pages';
$rquery= BD_Ejecutar($sql);
list($num_records)=mysql_fetch_row($rquery);
mysql_free_result($rquery);
$sql="SELECT id FROM pages WHERE RAND()*$num_records<20
ORDER BY RAND() LIMIT 0,10";
$rquery= BD_Ejecutar($sql);
while(list($id)=mysql_fetch_row($rquery)){
if($id_in) $id_in.=",$id";
else $id_in="$id";
}
mysql_free_result($rquery);
$sql="SELECT id,url FROM pages WHERE id IN($id_in)";
$rquery= BD_Ejecutar($sql);
while(list($id,$url)=mysql_fetch_row($rquery)){
logger("$id, $url",1);
}
mysql_free_result($rquery);
$time= microtime_float()-$time;
logger("num_records=$num_records",1);
logger("$id_in",1);
logger("Time elapsed: <b>$time segundos</b>",1);
?>
ORDER BY RAND()
FLUSH STATUS; SELECT ...; SHOW SESSION STATUS LIKE 'Handler%';
para verlo.
ORDER BY RAND()
es que clasifica solo los identificadores (no las filas completas), por lo que la tabla temporal es más pequeña, pero aún tiene que ordenarlos todos.
Su consulta de línea simple y muy simple.
SELECT * FROM Table_Name ORDER BY RAND() LIMIT 0,10;
order by rand()
es muy lento si la mesa es grande
Del libro:
Elija una fila aleatoria usando un desplazamiento
Aún otra técnica que evita los problemas encontrados en las alternativas anteriores es contar las filas en el conjunto de datos y devolver un número aleatorio entre 0 y el recuento. Luego use este número como compensación cuando consulte el conjunto de datos
<?php
$rand = "SELECT ROUND(RAND() * (SELECT COUNT(*) FROM Bugs))";
$offset = $pdo->query($rand)->fetch(PDO::FETCH_ASSOC);
$sql = "SELECT * FROM Bugs LIMIT 1 OFFSET :offset";
$stmt = $pdo->prepare($sql);
$stmt->execute( $offset );
$rand_bug = $stmt->fetch();
Utilice esta solución cuando no pueda asumir valores clave contiguos y necesite asegurarse de que cada fila tenga una posibilidad uniforme de ser seleccionada.
SELECT count(*)
vuelve lento.
Cómo seleccionar filas aleatorias de una tabla:
Desde aquí: seleccione filas aleatorias en MySQL
Una mejora rápida sobre el "escaneo de tabla" es utilizar el índice para recoger identificadores aleatorios.
SELECT *
FROM random, (
SELECT id AS sid
FROM random
ORDER BY RAND( )
LIMIT 10
) tmp
WHERE random.id = tmp.sid;
PRIMARY KEY
).
Bueno, si no tiene espacios en blanco en sus teclas y todas son numéricas, puede calcular números aleatorios y seleccionar esas líneas. pero esto probablemente no será el caso.
Entonces, una solución sería la siguiente:
SELECT * FROM table WHERE key >= FLOOR(RAND()*MAX(id)) LIMIT 1
que básicamente garantizará que obtenga un número aleatorio en el rango de sus teclas y luego seleccione el siguiente mejor que sea mayor. Tienes que hacer esto 10 veces.
sin embargo, esto NO es realmente aleatorio porque sus claves probablemente no se distribuirán de manera uniforme.
Es realmente un gran problema y no es fácil de resolver cumpliendo todos los requisitos, el rand () de MySQL es lo mejor que puede obtener si realmente desea 10 filas aleatorias.
Sin embargo, existe otra solución que es rápida, pero también tiene una compensación en lo que respecta a la aleatoriedad, pero puede ser mejor para usted. Lea sobre esto aquí: ¿Cómo puedo optimizar la función ORDER BY RAND () de MySQL?
La pregunta es qué tan aleatorio necesitas que sea.
¿Puedes explicarme un poco más para que pueda darte una buena solución?
Por ejemplo, una empresa con la que trabajé tenía una solución en la que necesitaban una aleatoriedad absoluta extremadamente rápida. Terminaron rellenando previamente la base de datos con valores aleatorios que se seleccionaron descendiendo y luego se establecieron en diferentes valores aleatorios nuevamente.
Si casi nunca actualiza, también puede completar una identificación incremental para que no tenga huecos y solo pueda calcular claves aleatorias antes de seleccionar ... ¡Depende del caso de uso!
Id
y todo sus consultas aleatorias le devolverán esa Id
.
FLOOR(RAND()*MAX(id))
está sesgado hacia la devolución de identificadores más grandes.
Necesitaba una consulta para devolver una gran cantidad de filas aleatorias de una tabla bastante grande. Esto es lo que se me ocurrió. Primero obtenga el ID de registro máximo:
SELECT MAX(id) FROM table_name;
Luego sustituya ese valor en:
SELECT * FROM table_name WHERE id > FLOOR(RAND() * max) LIMIT n;
Donde max es el ID de registro máximo en la tabla yn es el número de filas que desea en su conjunto de resultados. La suposición es que no hay vacíos en la identificación del registro, aunque dudo que afecte el resultado si los hubiera (aunque no lo he probado). También creé este procedimiento almacenado para ser más genérico; Pase el nombre de la tabla y el número de filas que se devolverán. Estoy ejecutando MySQL 5.5.38 en Windows 2008, 32 GB, E5450 dual de 3GHz, y en una tabla con 17.361.264 filas es bastante consistente en ~ .03 segundos / ~ 11 segundos para devolver 1,000,000 de filas. (los tiempos son de MySQL Workbench 6.1; también puede usar CEIL en lugar de FLOOR en la segunda instrucción de selección según su preferencia)
DELIMITER $$
USE [schema name] $$
DROP PROCEDURE IF EXISTS `random_rows` $$
CREATE PROCEDURE `random_rows`(IN tab_name VARCHAR(64), IN num_rows INT)
BEGIN
SET @t = CONCAT('SET @max=(SELECT MAX(id) FROM ',tab_name,')');
PREPARE stmt FROM @t;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @t = CONCAT(
'SELECT * FROM ',
tab_name,
' WHERE id>FLOOR(RAND()*@max) LIMIT ',
num_rows);
PREPARE stmt FROM @t;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
$$
entonces
CALL [schema name].random_rows([table name], n);
Todas las mejores respuestas ya se han publicado (principalmente las que hacen referencia al enlace http://jan.kneschke.de/projects/mysql/order-by-rand/ ).
Quiero señalar otra posibilidad de aceleración: el almacenamiento en caché . Piense por qué necesita obtener filas aleatorias. Probablemente desee mostrar alguna publicación aleatoria o anuncio aleatorio en un sitio web. Si obtiene 100 req / s, ¿es realmente necesario que cada visitante obtenga filas aleatorias? Por lo general, está bien almacenar en caché estas X filas aleatorias durante 1 segundo (o incluso 10 segundos). No importa si 100 visitantes únicos en el mismo 1 segundo obtienen las mismas publicaciones aleatorias, porque el siguiente segundo, otros 100 visitantes obtendrán un conjunto diferente de publicaciones.
Al usar este almacenamiento en caché, puede usar también una de las soluciones más lentas para obtener datos aleatorios, ya que se obtendrán de MySQL solo una vez por segundo, independientemente de sus requisitos / s.
Mejoré la respuesta que tenía @Riedsio. Esta es la consulta más eficiente que puedo encontrar en una tabla grande, distribuida uniformemente con espacios (probado al obtener 1000 filas aleatorias de una tabla que tiene> 2.6B filas).
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max := (SELECT MAX(id) FROM table)) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1)
Déjame desempacar lo que está pasando.
@max := (SELECT MAX(id) FROM table)
MAX(id)
cada vez que necesita una filaSELECT FLOOR(rand() * @max) + 1 as rand)
SELECT id FROM table INNER JOIN (...) on id > rand LIMIT 1
Hacer la unión lo ayuda a encajar todo en 1 consulta para que pueda evitar hacer múltiples consultas. También le permite guardar los gastos generales de cálculo MAX(id)
. Dependiendo de su aplicación, esto puede importar mucho o muy poco.
Tenga en cuenta que esto solo obtiene los identificadores y los obtiene en orden aleatorio. Si desea hacer algo más avanzado, le recomiendo que haga esto:
SELECT t.id, t.name -- etc, etc
FROM table t
INNER JOIN (
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max := (SELECT MAX(id) FROM table)) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1)
) x ON x.id = t.id
ORDER BY t.id
LIMIT 1
a LIMIT 30
todas partes en la consulta
LIMIT 1
a LIMIT 30
te daría 30 registros seguidos desde un punto aleatorio en la tabla. En su lugar, debe tener 30 copias de la (SELECT id FROM ....
parte en el medio.
Riedsio
responder. He intentado con 500 visitas por segundo a la página usando PHP 7.0.22 y MariaDB en centos 7, con la Riedsio
respuesta obtuve más de 500 respuestas exitosas adicionales y luego tu respuesta.
Utilicé este http://jan.kneschke.de/projects/mysql/order-by-rand/ publicado por Riedsio (utilicé el caso de un procedimiento almacenado que devuelve uno o más valores aleatorios):
DROP TEMPORARY TABLE IF EXISTS rands;
CREATE TEMPORARY TABLE rands ( rand_id INT );
loop_me: LOOP
IF cnt < 1 THEN
LEAVE loop_me;
END IF;
INSERT INTO rands
SELECT r1.id
FROM random AS r1 JOIN
(SELECT (RAND() *
(SELECT MAX(id)
FROM random)) AS id)
AS r2
WHERE r1.id >= r2.id
ORDER BY r1.id ASC
LIMIT 1;
SET cnt = cnt - 1;
END LOOP loop_me;
En el artículo, resuelve el problema de las brechas en los identificadores que causan resultados no tan aleatorios al mantener una tabla (usando desencadenantes, etc. ... vea el artículo); Estoy resolviendo el problema agregando otra columna a la tabla, poblada con números contiguos, comenzando desde 1 ( editar: esta columna se agrega a la tabla temporal creada por la subconsulta en tiempo de ejecución, no afecta su tabla permanente):
DROP TEMPORARY TABLE IF EXISTS rands;
CREATE TEMPORARY TABLE rands ( rand_id INT );
loop_me: LOOP
IF cnt < 1 THEN
LEAVE loop_me;
END IF;
SET @no_gaps_id := 0;
INSERT INTO rands
SELECT r1.id
FROM (SELECT id, @no_gaps_id := @no_gaps_id + 1 AS no_gaps_id FROM random) AS r1 JOIN
(SELECT (RAND() *
(SELECT COUNT(*)
FROM random)) AS id)
AS r2
WHERE r1.no_gaps_id >= r2.id
ORDER BY r1.no_gaps_id ASC
LIMIT 1;
SET cnt = cnt - 1;
END LOOP loop_me;
En el artículo, puedo ver que hizo todo lo posible para optimizar el código; No tengo idea de si / cuánto mis cambios afectan el rendimiento, pero funciona muy bien para mí.
@no_gaps_id
índice no se puede utilizar, por lo que si observa EXPLAIN
su consulta, tiene Using filesort
y Using where
(sin índice) para las subconsultas, en contraste con la consulta original.
Aquí hay un cambio de juego que puede ser útil para muchos;
Tengo una tabla con 200k filas, con identificaciones secuenciales , necesitaba elegir N filas aleatorias, por lo que opto por generar valores aleatorios basados en la ID más grande de la tabla, creé este script para descubrir cuál es la operación más rápida:
logTime();
query("SELECT COUNT(id) FROM tbl");
logTime();
query("SELECT MAX(id) FROM tbl");
logTime();
query("SELECT id FROM tbl ORDER BY id DESC LIMIT 1");
logTime();
Los resultados son:
36.8418693542479
ms0.241041183472
ms0.216960906982
msEn base a estos resultados, la descripción del pedido es la operación más rápida para obtener la identificación máxima.
Aquí está mi respuesta a la pregunta:
SELECT GROUP_CONCAT(n SEPARATOR ',') g FROM (
SELECT FLOOR(RAND() * (
SELECT id FROM tbl ORDER BY id DESC LIMIT 1
)) n FROM tbl LIMIT 10) a
...
SELECT * FROM tbl WHERE id IN ($result);
FYI: para obtener 10 filas aleatorias de una tabla de 200k, me llevó 1,78 ms (incluidas todas las operaciones en el lado php)
LIMIT
poco, puedes obtener duplicados.
Esto es súper rápido y es 100% aleatorio incluso si tienes huecos.
x
de filas que tiene disponiblesSELECT COUNT(*) as rows FROM TABLE
a_1,a_2,...,a_10
entre 0 yx
SELECT * FROM TABLE LIMIT 1 offset a_i
para i = 1, ..., 10Encontré este truco en el libro SQL Antipatterns de Bill Karwin .
SELECT column FROM table ORDER BY RAND() LIMIT 10
está en O (nlog (n)). Entonces sí, esta es la solución en ayunas y funciona para cualquier distribución de identificadores.
x
. Yo diría que esta no es una generación aleatoria de 10 filas. En mi respuesta, debe ejecutar la consulta en el paso tres 10 veces, es decir, una solo obtiene una fila por ejecución y no tiene que preocuparse si el desplazamiento está al final de la tabla.
Combina la respuesta de @redsio con una tabla temporal (600K no es tanto):
DROP TEMPORARY TABLE IF EXISTS tmp_randorder;
CREATE TABLE tmp_randorder (id int(11) not null auto_increment primary key, data_id int(11));
INSERT INTO tmp_randorder (data_id) select id from datatable;
Y luego tome una versión de @redsios Respuesta:
SELECT dt.*
FROM
(SELECT (RAND() *
(SELECT MAX(id)
FROM tmp_randorder)) AS id)
AS rnd
INNER JOIN tmp_randorder rndo on rndo.id between rnd.id - 10 and rnd.id + 10
INNER JOIN datatable AS dt on dt.id = rndo.data_id
ORDER BY abs(rndo.id - rnd.id)
LIMIT 1;
Si la mesa es grande, puede tamizar en la primera parte:
INSERT INTO tmp_randorder (data_id) select id from datatable where rand() < 0.01;
Versión: puedes quedarte con la mesa tmp_randorder
persistente, llámela datatable_idlist. Recree esa tabla en ciertos intervalos (día, hora), ya que también tendrá agujeros. Si su mesa se vuelve muy grande, también puede rellenar agujeros
seleccione l.data_id como un todo de datatable_idlist l left join datatable dt on dt.id = l.data_id donde dt.id es nulo;
Versión: asigne a su conjunto de datos una columna de orden aleatorio directamente en la tabla de datos o en una tabla adicional persistente datatable_sortorder
. Indice esa columna. Genere un valor aleatorio en su aplicación (lo llamaré $rand
).
select l.*
from datatable l
order by abs(random_sortorder - $rand) desc
limit 1;
Esta solución discrimina las 'filas de borde' con el orden aleatorio más alto y el más bajo, por lo que debe reorganizarlas en intervalos (una vez al día).
Otra solución simple sería clasificar las filas y buscar una de ellas al azar y con esta solución no necesitará tener ninguna columna basada en 'Id' en la tabla.
SELECT d.* FROM (
SELECT t.*, @rownum := @rownum + 1 AS rank
FROM mytable AS t,
(SELECT @rownum := 0) AS r,
(SELECT @cnt := (SELECT RAND() * (SELECT COUNT(*) FROM mytable))) AS n
) d WHERE rank >= @cnt LIMIT 10;
Puede cambiar el valor límite según su necesidad de acceder a tantas filas como desee, pero en su mayoría serían valores consecutivos.
Sin embargo, si no desea valores aleatorios consecutivos, puede obtener una muestra más grande y seleccionarla aleatoriamente. algo como ...
SELECT * FROM (
SELECT d.* FROM (
SELECT c.*, @rownum := @rownum + 1 AS rank
FROM buildbrain.`commits` AS c,
(SELECT @rownum := 0) AS r,
(SELECT @cnt := (SELECT RAND() * (SELECT COUNT(*) FROM buildbrain.`commits`))) AS rnd
) d
WHERE rank >= @cnt LIMIT 10000
) t ORDER BY RAND() LIMIT 10;
Una forma en que me parece bastante bueno si hay una identificación autogenerada es usar el operador de módulo '%'. Por ejemplo, si necesita 10,000 registros aleatorios de 70,000, podría simplificar esto diciendo que necesita 1 de cada 7 filas. Esto se puede simplificar en esta consulta:
SELECT * FROM
table
WHERE
id %
FLOOR(
(SELECT count(1) FROM table)
/ 10000
) = 0;
Si el resultado de dividir las filas de destino por el total disponible no es un número entero, tendrá algunas filas adicionales de las que solicitó, por lo que debe agregar una cláusula LIMIT para ayudarlo a recortar el conjunto de resultados de esta manera:
SELECT * FROM
table
WHERE
id %
FLOOR(
(SELECT count(1) FROM table)
/ 10000
) = 0
LIMIT 10000;
Esto requiere un escaneo completo, pero es más rápido que ORDER BY RAND, y en mi opinión es más fácil de entender que otras opciones mencionadas en este hilo. Además, si el sistema que escribe en la base de datos crea conjuntos de filas en lotes, es posible que no obtenga un resultado tan aleatorio como esperaba.
Si desea un registro aleatorio (no importa si hay espacios entre los identificadores):
PREPARE stmt FROM 'SELECT * FROM `table_name` LIMIT 1 OFFSET ?';
SET @count = (SELECT
FLOOR(RAND() * COUNT(*))
FROM `table_name`);
EXECUTE stmt USING @count;
He revisado todas las respuestas, y no creo que nadie mencione esta posibilidad en absoluto, y no estoy seguro de por qué.
Si desea la máxima simplicidad y velocidad, a un costo menor, entonces para mí parece tener sentido almacenar un número aleatorio en cada fila de la base de datos. Simplemente cree una columna adicional random_number
, y configure su valor predeterminado en RAND()
. Crea un índice en esta columna.
Luego, cuando desee recuperar una fila, genere un número aleatorio en su código (PHP, Perl, lo que sea) y compárelo con la columna.
SELECT FROM tbl WHERE random_number >= :random LIMIT 1
Supongo que aunque es muy ordenado para una sola fila, para diez filas como el OP le pidió que tuviera que llamarlo diez veces por separado (o presentar un ajuste inteligente que se me escape de inmediato)
Lo siguiente debe ser rápido, imparcial e independiente de la columna de identificación. Sin embargo, no garantiza que el número de filas devueltas coincida con el número de filas solicitadas.
SELECT *
FROM t
WHERE RAND() < (SELECT 10 / COUNT(*) FROM t)
Explicación: suponiendo que desea 10 filas de 100, cada fila tiene 1/10 de probabilidad de ser SELECCIONADO, lo que podría lograrse mediante WHERE RAND() < 0.1
. Este enfoque no garantiza 10 filas; pero si la consulta se ejecuta suficientes veces, el número promedio de filas por ejecución será de alrededor de 10 y cada fila de la tabla se seleccionará de manera uniforme.
PREPARE stm from 'select * from table limit 10 offset ?';
SET @total = (select count(*) from table);
SET @_offset = FLOOR(RAND() * @total);
EXECUTE stm using @_offset;
También puede aplicar una cláusula where así
PREPARE stm from 'select * from table where available=true limit 10 offset ?';
SET @total = (select count(*) from table where available=true);
SET @_offset = FLOOR(RAND() * @total);
EXECUTE stm using @_offset;
Probado en 600,000 filas (700MB), la ejecución de la consulta de la tabla tomó ~ 0.016sec HDD drive
--EDIT--
El desplazamiento puede tomar un valor cercano al final de la tabla, lo que dará como resultado que la instrucción select devuelva menos filas (o tal vez solo 1 fila), para evitar esto, podemos verificar offset
nuevamente después de declararlo, así
SET @rows_count = 10;
PREPARE stm from "select * from table where available=true limit ? offset ?";
SET @total = (select count(*) from table where available=true);
SET @_offset = FLOOR(RAND() * @total);
SET @_offset = (SELECT IF(@total-@_offset<@rows_count,@_offset-@rows_count,@_offset));
SET @_offset = (SELECT IF(@_offset<0,0,@_offset));
EXECUTE stm using @rows_count,@_offset;
Yo uso esta consulta:
select floor(RAND() * (SELECT MAX(key) FROM table)) from table limit 10
tiempo de consulta: 0.016s
Así es como lo hago:
select *
from table_with_600k_rows
where rand() < 10/600000
limit 10
Me gusta porque no requiere otras tablas, es simple de escribir y es muy rápido de ejecutar.
Use la consulta simple a continuación para obtener datos aleatorios de una tabla.
SELECT user_firstname ,
COUNT(DISTINCT usr_fk_id) cnt
FROM userdetails
GROUP BY usr_fk_id
ORDER BY cnt ASC
LIMIT 10
Supongo que esta es la mejor manera posible ...
SELECT id, id * RAND( ) AS random_no, first_name, last_name
FROM user
ORDER BY random_no