2012-03-08 16 views
5

Mam kwerendy MySQL, że wyniki w coś takiego:Wybierz losowy wiersz dla różnych wartości pola?

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

(To jest tylko uproszczonym przykładem W rzeczywistości istnieje około 5000 wierszy w moich wynikach.).

Co muszę zrobić, to przejść przez każdą osobę na liście (Bob, John, Alex, itp ...) i wyciągnąć wiersz z ich zestawu wyników. Rząd, który wyciągam, jest przypadkowy, ale także oparty na luźnym zestawie warunków. To naprawdę nie jest ważne, aby określić warunki tutaj, więc powiem po prostu, że jest to losowy wiersz dla przykładu.

W każdym razie, używając PHP, to rozwiązanie jest całkiem proste. Wykonuję moje zapytanie i uzyskuję 5000 wierszy wstecz i iteruję je, wyciągając losowy wiersz dla każdej osoby. Łatwo.

Zastanawiam się jednak, czy można uzyskać to, co chciałbym, z tylko kwerendy MySQL, tak, że nie muszę używać PHP do iteracji wyników i wyciągania losowych wierszy.

Mam przeczucie, że może obejmować BUNCH subselects, jak jeden dla każdej osoby, w którym to przypadku to rozwiązanie będzie więcej czasu, zasobów i przepustowości niż moje obecne rozwiązanie.

Czy istnieje sprytne zapytanie, które może wykonać to wszystko za pomocą jednego polecenia?

Here is an SQLFiddle z którym można grać.

+0

Trudno powiedzieć, nie znając warunków.Naiwna odpowiedź: jeśli nie potrzebujesz danych w 'some_info', po prostu wybierz osobę, GDZIE/* tu warunki * /' – bfavaretto

+0

Potrzebuję 'some_info'. –

Odpowiedz

6

Aby uzyskać losową wartość odrębną nazwą używać

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 ; 

umieścić to zapytanie, ponieważ stoi w sqlfiddle i będzie działać

im przy R i R1 jako nazwy tabeli aliasu. Będzie to również użyć podzapytania, aby wybrać losowy some_info nazwy

SQL Fiddle is here

+0

Ciekawe ... czy to zasadniczo uruchamia dodatkowe zapytanie SELECT dla każdego imienia? Podobnie jak w przypadku SQLFiddle, w tabeli znajduje się 10 różnych nazw. Czy powyższa kwerenda w zasadzie wykonuje na raz 1 + 10 = 11 zapytań? –

+0

Tak ... to sposób na obejrzenie tego. Chociaż to jest sposób, który działa. Spójrz na http://dev.mysql.com/doc/refman/5.0/en/scalar-subqueries.html – bretterer

+0

jeszcze jedno pytanie dla ciebie, gdybym miał więcej kolumn niż tylko 'some_info', które musiałem zwrócić w to pod-zapytanie, jak bym to zrobił? Wydaje się, że MySQL pozwala mi tylko zwrócić jedną kolumnę w pod-zapytaniu ... –

0

Możesz ograniczyć liczbę zapytań i porządku za pomocą "rand()", aby uzyskać pożądany wynik.

Może gdybyś spróbował coś takiego:

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

To by tylko zwróciło jeden wynik ... czy czegoś brakuje? –

0

Moja pierwsza reakcja byłoby użyć PHP do generowania liczb losowych:

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

Następnie uruchom zapytanie SQL, które pobiera rekord, w którym indeks jest równy $ randID.

0

Oto rozwiązanie:

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 
) 

Stół użyty w przykładzie poniżej:

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

Rozwiązanie nie ogranicza liczby rekordów na osobę ani całości, itp. – kasavbere

+0

bty: "count (person) c, min (id) i" nie jest konieczne: Zapomniałem usunąć go z ostatecznej odpowiedzi. Po prostu zamów przez min (id). – kasavbere

Powiązane problemy