Obtener registro aleatorio por tipo de usuario en BD MySQL

Vzk91 Seguir

Eta
Programador
Verificación en dos pasos activada
Desde
13 Abr 2012
Mensajes
1.468
Hola,

Veréis me encuentro con la siguiente situación. Tengo una tabla llamemosla Usuario, el cual tiene una serie de campos. Uno de esos campos es tipoUsuario, que puede ser de 7 tipos. Lo que intento lograr es obtener un registro aleatorio a consultas del tipo:

SELECT * FROM Usuario WHERE tipoUsuario = '1'
SELECT * FROM Usuario WHERE tipoUsuario = '2'
SELECT * FROM Usuario WHERE tipoUsuario = '3'
.....

Hasta ahora lo que habia estado intentando era generar un numero aleatorio en PHP comprendido entre el máximo y mínimo valor de los IDs de cada usuario. El problema es que los usuarios se van registrando de manera aleatoria por lo que podemos tener la siguiente situacion:

IDs del 1 al 7 -> Tipo 1
IDs del 8 al 20 -> Tipo 2
IDs del 21 al 24 -> Tipo 1
....

Si cojo el máximo y mínimo ID del tipo 1 me dará 24 y 1 respectivamente.... pero los IDS entre el 8 y el 20 son del tipo 2, por lo que si genero con php un valor aleatorio entre 1 y 24 va a dar muchos problemas ya que hay 12 numeros internos que no hay que tener en cuenta....

Alguna forma decente de obtener un registro aleatorio para cada tipo de usuario ?

Hay que tener en cuenta que la tabla contiene cerca de 10.000 registros.

un saludo
 

lombervid

Zeta
Verificación en dos pasos activada
Desde
29 Abr 2011
Mensajes
1.509
Porque no, por ejemplo, haces tu consulta "SELECT * FROM Usuario WHERE tipoUsuario = '1'" y generas un número aleatorio dependiendo de los resultados que te arroje, por ejemplo digamos que te arrojo 20 resultados, generas un número aleatorio entre 1 y 20 y agarras esa posicion.

Saludos!
 

Vzk91

Eta
Programador
Verificación en dos pasos activada
Desde
13 Abr 2012
Mensajes
1.468
Porque no, por ejemplo, haces tu consulta "SELECT * FROM Usuario WHERE tipoUsuario = '1'" y generas un número aleatorio dependiendo de los resultados que te arroje, por ejemplo digamos que te arrojo 20 resultados, generas un número aleatorio entre 1 y 20 y agarras esa posicion.

Saludos!

Ese es el problema que describo. Si hago la consulta como tu dices, por ejemplo voy a obtener esta serie de ids:

1,2,3,7,9,10,15,16,18,19,20

Como ves los ids 4,5,6,8,11,12,13,14 y 17 no forman parte de los usuarios de tipo 1, por lo que si genero un numero aleatorio y resulta que es uno de esos ids que no entran en el rango la aplicación no funciona correctamente.
 

SrSagek

Beta
Verificado por Whatsapp
¡Usuario con pocos negocios! ¡Utiliza siempre saldo de Forobeta!
Desde
8 May 2013
Mensajes
136
Y si en la consulta generas un xml asignandole un nuevo id a cada linea de la consulta... luego haces un random entre el 0 y el ultimo numero del id del xml y ya esta. No?
 

Vzk91

Eta
Programador
Verificación en dos pasos activada
Desde
13 Abr 2012
Mensajes
1.468
Y si en la consulta generas un xml asignandole un nuevo id a cada linea de la consulta... luego haces un random entre el 0 y el ultimo numero del id del xml y ya esta. No?

Esta forma no me la habia planteado, voy echarle un vistazo.

Tambien he encontado una forma de conseguirlo mezclando el PHP con MYSQL pero desconozco de su funcionamiento con tablas de gran volumen:

PHP:
$query = mysql_query("SELECT * FROM Usuario WHERE tipoUsuario = '1' ORDER BY rand(" . time() . " * " . time() .  ") LIMIT 1");

sabeis algo de este metodo ?
 

SrSagek

Beta
Verificado por Whatsapp
¡Usuario con pocos negocios! ¡Utiliza siempre saldo de Forobeta!
Desde
8 May 2013
Mensajes
136
Yo creo que así podria valer, nunca he utilizado el comando rand de mysql pero tiene pinta de que está bien. Ordenas aleatoriamente y luego coges el primer registro solo. Lo veo bien :p8:
 

lombervid

Zeta
Verificación en dos pasos activada
Desde
29 Abr 2011
Mensajes
1.509
Ese es el problema que describo. Si hago la consulta como tu dices, por ejemplo voy a obtener esta serie de ids:

1,2,3,7,9,10,15,16,18,19,20

Como ves los ids 4,5,6,8,11,12,13,14 y 17 no forman parte de los usuarios de tipo 1, por lo que si genero un numero aleatorio y resulta que es uno de esos ids que no entran en el rango la aplicación no funciona correctamente.

Pero a lo que yo me refiero es:

Suponiendo que esto te devuelve la consulta "1,2,3,7,9,10,15,16,18,19,20" son 11 registros, entonces generas un número entre 1 y 11, digamos que te toco 5, entonces agarras la posicion 5 (de los que te devolvio, no del id) que vendria siendo el 9.

Saludos!
 

Vzk91

Eta
Programador
Verificación en dos pasos activada
Desde
13 Abr 2012
Mensajes
1.468
Pero a lo que yo me refiero es:

Suponiendo que esto te devuelve la consulta "1,2,3,7,9,10,15,16,18,19,20" son 11 registros, entonces generas un número entre 1 y 11, digamos que te toco 5, entonces agarras la posicion 5 (de los que te devolvio, no del id) que vendria siendo el 9.

Saludos!

Hablado en numeros bajos es la forma mas optima, pero suponte que la consulta de vuelve 3000 registros, crear en php un array de 3000 registros supone un consumo de recursos considerable.... por eso descarte esa opcion.

Por lo que he leido la forma que comente anteriormente tampoco es muy recomendable usarla con grandes volumenes de registros pero si es cierto que la carga se produce en el lado del servidor MySQL.... asique por el momento creo que usare esta forma...
 

Joscplan

Gamma
Programador
Verificación en dos pasos activada
Desde
20 Jun 2013
Mensajes
439
Insertar CODE, HTML o PHP:
$query = mysql_query("SELECT * FROM Usuario WHERE tipoUsuario = '1' ORDER BY rand(" . time() . " * " . time() .  ") LIMIT 1");

Esa es la única que te podría servir dado el número lo que no necesitas ahcer es " . time() . " * " . time() . " ya que estás poniendo como regla que solo estén los del tipo 1 por lo que solo lanzará los usuarios que su tipo sea 1 luego la función rand() te lanzará uno al azar.

Por lo que vendría siendo algo así:

Insertar CODE, HTML o PHP:
$query = mysql_query("SELECT * FROM Usuario WHERE tipoUsuario = 1 ORDER BY RAND() LIMIT 1");
 

IgnacioViglo

Beta
¡Usuario con pocos negocios! ¡Utiliza siempre saldo de Forobeta!
Desde
31 Dic 2012
Mensajes
55
Por ahí no se recomienda mucho el uso de RAND() pero creo que para este caso es lo mejor, hacé lo que te dijo el compañero de arriba
 

Cazamitos

Delta
Verificación en dos pasos activada
Verificado por Whatsapp
Desde
20 Abr 2011
Mensajes
738
La respuesta es sencilla, utiliza :

select count(*) from 'your_table'

Al número que te salga hazle un random desde PHP

SELECT * FROM `your_table` LIMIT (Aquí pon el resultado del random), 1
 

Kabytes

Curioso
¡Usuario con pocos negocios! ¡Utiliza siempre saldo de Forobeta!
Desde
3 Jul 2013
Mensajes
7
Se me ocurre tambien otro tipo de consulta. Eso si, bastante pesadita, el punto positivo es que te solucionaria todo en una sola consulta compuesta y te devolveria directamente el resultado final que necesitas mostrar.

Con esta consulta obtendrías, el id aleatorio de cada grupo por resultado con el registro completo (según adiciones campos a los selects)

PHP:
SELECT id, name, tipoUSuario 
      FROM (SELECT id, name, tipoUSuario FROM Usuarios order by rand()) as t 
      GROUP BY tipoUsuario;

Ojo, no es una consulta optima, puede ser útil según el numero de registros que tengas, tambien si es una consulta que puedes realizar cada x tiempo y permita el cacheo de datos.

Pero bueno, te diria que la pruebes y veas como responde la base de datos. Es otra forma.
 

antonrodin

Beta
Verificación en dos pasos activada
Verificado por Whatsapp
Desde
6 Jul 2012
Mensajes
146
Al obtener la consulta creo que ya estaría dentro de un Array o Objeto, dependiendo de lo que uses. Sobre el consumo re recursos el coste es lineal, es decir O(n) o menos. Ademas lógicamente lo suyo que solo hagas consulta para sacar los ID...

Otro gallo cantaría cuando escribes en la BD, que ahí el coste es mucho mayor :ambivalence:

En fin, yo utilizaría arrays de integer, siempre y cuando el tamaño de base de datos no sea de "cientos de miles o millones de filas" donde miraría algún tipo de cache...

También puedes utilizar el algoritmo de montecarlo, creo que se llama así. Es muy fácil... haces random(ID) hasta que este ID exista en la BD. Si no borras mucho, la mayoría de veces tu bucle tendrá un coste 1 o 2:

encontrado = false;
Mientras (!encontrado) do
random(ID)
SELECT ...WHERE ID = ....
if existe encontrado= true
end

:s
 
Arriba