2012-03-08 17 views
5

Tengo una consulta MySQL que resulta en algo como esto:¿Seleccionar una fila aleatoria por valor de campo distinto?

person | some_info 
================== 
    bob | pphsmbf24 
    bob | rz72nixdy 
    bob | rbqqarywk 
    john | kif9adxxn 
    john | 77tp431p4 
    john | hx4t0e76j 
    john | 4yiomqv4i 
    alex | n25pz8z83 
    alex | orq9w7c24 
    alex | beuz1p133 
    etc... 

(Esto es sólo un ejemplo simplificado En realidad hay alrededor de 5.000 filas en mis resultados.).

Lo que tengo que hacer es ir a través de cada persona en la lista (bob, john, alex, etc.) y sacar una fila de su conjunto de resultados. La fila que saco es algo aleatoria, pero también se basa en un conjunto de condiciones imprecisas. No es realmente importante especificar las condiciones aquí, así que solo diré que es una fila aleatoria para el ejemplo.

De todos modos, usando PHP, esta solución es bastante simple. Realizo mi consulta y recupero 5000 filas e itero a través de ellas extrayendo mi fila aleatoria para cada persona. Fácil.

Sin embargo, me pregunto si es posible obtener lo que obtendría de solo una consulta MySQL para no tener que usar PHP para recorrer los resultados y sacar mis filas aleatorias.

Tengo la sensación de que podría involucrar un BUNCH de subselects, como uno para cada persona, en cuyo caso esa solución requeriría más tiempo, recursos y ancho de banda que mi solución actual.

¿Existe alguna consulta inteligente que pueda realizar este comando todo en uno?

Here is an SQLFiddle con el que puedes jugar.

+0

Difícil de decir, sin conocer las condiciones.Respuesta ingenua: si no necesita los datos en 'some_info', simplemente' SELECCIONE la persona DISTINCT DONDE/* usted condiciona aquí */' – bfavaretto

+0

Necesito el' some_info'. –

Respuesta

6

para obtener un valor aleatorio para utilizar un nombre distinto

SELECT r.name, 
(SELECT r1.some_info FROM test AS r1 WHERE r.name=r1.name ORDER BY rand() LIMIT 1) AS  'some_info' 
FROM test AS r 
GROUP BY r.name ; 

Deja esta consulta tal y como está en su sqlfiddle y funcionará

Im usando R y R1 como nombres de tabla de alias. Esto también utilizar una subconsulta para seleccionar un some_info aleatorio para el nombre

SQL Fiddle is here

+0

Interesante ... ¿Básicamente es ejecutar una consulta SELECT extra para cada nombre? Al igual que en SQLFiddle, hay 10 nombres distintos en la tabla. ¿La consulta anterior básicamente ejecuta 1 + 10 = 11 consultas todas a la vez? –

+0

Sí ... esa es una manera de verlo. Aunque esta es la forma en que funciona. Eche un vistazo a http://dev.mysql.com/doc/refman/5.0/en/scalar-subqueries.html – bretterer

+0

una pregunta más para usted, si tuviera más columnas que solo 'some_info' que necesitaba devolver en esa subconsulta, ¿cómo podría hacer eso? MySQL solo me permite devolver una sola columna en la subconsulta ... –

0

Puede limitar el número de consultas y ordenar por "rand()" para obtener el resultado deseado.

Tal vez si se trató de algo como esto:

SELECT name, some_info 
    FROM test 
WHERE name = 'tara' 
ORDER BY rand() 
LIMIT 1 
+1

Eso solo devolvería un solo resultado ... ¿me estoy perdiendo algo? –

0

Mi primera respuesta sería utilizar PHP para generar un número aleatorio:

$ randId = rand ($ min, $ max);

Luego ejecute una consulta SQL que solo obtiene el registro donde su índice equivale a $ randID.

0

Aquí está la solución:

select person, acting from personel where id in (
select lim from 
    (select count(person) c, min(id) i, cast(rand()*(count(person)-1) +min(id) 
      as unsigned) lim from personel group by person order by i) t1 
) 

La tabla utilizada en el ejemplo es el siguiente:

create table personel (
id int(11) not null auto_increment, 
person char(16), 
acting char(19), 
primary key(id) 

);

insert into personel (person,acting) values 
('john','abd'),('john','aabd'),('john','adbd'),('john','abfd'), 
('alex','ab2d'),('alex','abd3'),('alex','ab4d'),('alex','a6bd'), 
('max','ab2d'),('max','abd3'),('max','ab4d'),('max','a6bd'), 
('jimmy','ab2d'),('jimmy','abd3'),('jimmy','ab4d'),('jimmy','a6bd'); 
+0

La solución no limita el número de registros por persona o total, etc. – kasavbere

+0

bty: "count (person) c, min (id) i," no es necesario: olvidé eliminarlo de la respuesta final. Solo pida por min (id). – kasavbere

Cuestiones relacionadas