2012-03-08 7 views
5

У меня есть запрос MySQL, что приводит к чему-то вроде этого:Выберите случайную строку для отдельного значения поля?

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

(Это просто упрощенный пример В действительности существует около 5000 строк в моих результатах.).

Что мне нужно сделать, это пройти через каждого человека в списке (bob, john, alex и т. Д.) И вытащить строку из их набора результатов. Строка, которую я вытаскиваю, похожа на случайную, но вроде также на основе свободного набора условий. Здесь не важно указывать условия, поэтому я просто скажу, что это случайная строка для примера.

В любом случае, используя PHP, это решение довольно просто. Я делаю свой запрос и получаю 5000 строк назад и перебираю их, вытаскивая свою случайную строку для каждого человека. Легко.

Тем не менее, мне интересно, можно ли получить то, что я хотел бы только из MySQL-запроса, чтобы мне не пришлось использовать PHP для повторения результатов и вытаскивания моих случайных строк.

У меня возникло ощущение, что это может включать в себя подсчеты подзапросов, как и для каждого человека, и в этом случае это решение будет больше времени, ресурсов и пропускной способности, чем мое текущее решение.

Есть ли умный запрос, который может выполнить все это в одной команде?

Here is an SQLFiddle, с которым вы можете играть.

+0

Трудно сказать, не зная условий.Наивный ответ: если вам не нужны данные в 'some_info', просто' SELECT DISTINCT person WHERE/* здесь вы здесь */' – bfavaretto

+0

Мне нужно' some_info'. –

ответ

6

Чтобы получить случайное значение для отдельного имени использовать

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 ; 

Поместите этот запрос, как он стоит в вашем sqlfiddle и он будет работать

Im используя г и г1 в качестве имен таблицы псевдонимов. Это также будет использовать подзапрос для выбора случайного some_info для имени

SQL Fiddle is here

+0

Интересно ... это в основном запуск дополнительного запроса SELECT для каждого имени? Например, в SQLFiddle есть 10 различных имен в таблице. Является ли приведенный выше запрос в основном выполнением 1 + 10 = 11 запросов одновременно? –

+0

Да ... это способ взглянуть на него. Хотя это так работает. Взгляните на http://dev.mysql.com/doc/refman/5.0/en/scalar-subqueries.html – bretterer

+0

еще один вопрос для вас, если бы у меня было больше столбцов, чем просто 'some_info', которые мне нужно было вернуть в этот подзапрос, как бы я это сделал? MySQL только, кажется, позволяет мне возвращать один столбец в подзапросе ... –

0

Вы можете ограничить количество запросов и заказать «rand()», чтобы получить желаемый результат.

Возможно, если бы вы пытались что-то вроде этого:

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

Это вернет только один результат ... Я что-то упустил? –

0

Моя первая реакция будет использовать PHP для генерации случайных чисел:

$ randId = рандов ($ мин, $ макс);

Затем запустите SQL-запрос, который получает только запись, где ваш индекс равен $ randID.

0

Вот решение:

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 
) 

В таблице, используемый в примере ниже:

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

Решение не налагает ограничений на количество записей на человека или всего и т. Д. – kasavbere

+0

bty: «count (person) c, min (id) i» не требуется: я забыл удалить его из окончательного ответа. Просто закажите по мин (id). – kasavbere

Смежные вопросы