(Polski) MySQL RAND() – jak pobrać losowe wiersze

Sorry, this entry is only available in Polski.

 

Przeczytaj także

Komentarze: 12

Dodaj komentarz »

 
 
Marcin Kłeczek
 

Świetny tekst – o bardzo popularnym problemie – i jak widać, często źle rozwiązywanym. Dzięki.

 

Reply

 

Niestety kombinacja “ORDER BY RAND()” jest mordercza, ale często powtarzana i w wielu małych aplikacjach się zdarza…

Wiesz, nieraz lepiej zrobić 2 proste zapytania resztę zrzucając na język programowania, niż jedno przepakowane.

 

Reply

 

Ciekawy tekst i proponowane rozwiązania. Jest jednak jedno “ale”. Mianowicie tych metod, jako że korzystają z MAX(id), MIN(id) etc., nie można wykorzystać w przypadku, kiedy identyfikatory kolejnych rekordów nie utrzymują ciągłości. Tzn. jeśli np. jakiś rekord zostanie wykasowany fizycznie z bazy, to jest szansa, że losowanie z zakresu pomiędzy MIN a MAX może trafić w ten właśnie rekord.
Możliwe, że to m.in. dlatego funkcja: SELECT `id`,`key` FROM `keys`ORDER BY RAND() LIMIT 1; potrafi zająć tyle czasu – ale przynajmniej w jej przypadku można być pewnym zwracanego wyniku.

 

Reply

 

@Rumcajs
Tak, masz rację, właśnie dlatego pisałem na końcu części “Satysfakcjonujące rozwiązanie” o tabeli tymczasowej, która przechowywałaby klucze do istniejących rekordów: ID | KEY_ID , a całe losowanie id wykonywane byłoby na tej tabeli tymczasowej.

 

Reply

 

@Rumcjajs: wg mojego czytania ze zrozumieniem – mylisz się 😉
Dlatego “ktoś” napisał warunek: WHERE `id` >= $random aby uniknąć wpadnięcia pod MIN/MAX gdy rekord już usunięty…
Oczywiście brzydkie rozwiązanie, ale działa tak jak autor napisał

 

Reply

     

    @matipl: tu chodzi o sytuacje kiedy nie bedzie istnial rekord pomiędzy min id a max id.
    Jeśli sa id: 2,3,4,6,7 to min jest 2 max 7 a może się wylosować 5.
    O tym napisał @Rumcajs

     

    Reply

       

      @quentino: Dlatego w warunku WHERE jest `id`>=, w przypadku gdy nie ma wiersza o id 5 zostanie zwrócony następny w kolejności (istniejący)

       

      Reply

 

Warunek WHERE jest `id`>=, nie powoduje losowego wybrania elementu z bazy, gdyz faworyzuje pewne elementy
przyklad
mamy id: 1,2,3,7,8,9
najczesciej losowanym elementem bedzie 7 i to az 4 razy czeesciej niz inne.

 

Reply

 

Fajne rozwiązanie na które kiedyś się natknąłem i często stosuję to zliczenie wszystkich wierszy, wylosowanie numeru strony, a następnie pobranie losowej strony. Działa szybko i jest proste.

 

Reply

 

SET @r := (SELECT ROUND(RAND() * (SELECT COUNT(*) FROM tabelka)));
SET @sql := CONCAT(‘SELECT * FROM tabelka LIMIT 1 OFFSET ‘, @r);
PREPARE stmt1 FROM @sql;
EXECUTE stmt1;

powinno dzialac i nie ma problemu z ciagloscia rekordow

 

Reply

 

Skąd takie czasy? “1 row in set (0.61 sec)”

Kiedy u mnie przy 20tys rekordów i limit 10 wychodzi: “10 wszystkich, Wykonanie zapytania trwało 0.0222 sekund(y))”

Przy 100tys tak drastycznie wzrosło? Wątpię.

 

Reply

 

Szczerze, dopiero zaczynam swoją przygodę z Mysql ale wpadłem na pewien pomysł, który powinna zweryfikować osoba posiadająca większą wiedzę.

Czy wydajnym nie było by wykonanie zapytania num() o ilość rekordów, następnie za pomocą mt_randa określenie jakiegoś limitu w zapytaniu, a następnie wylosowanie wśród tych, dajmy na to 10 losowych rekordów?

 

Reply

 

Dodaj komentarz

 
(nie będzie publikowany)
 
 
Komentarz
 
 

Dozwolone tagi XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

 
© 2009 - 2018 Vokiel.com
WordPress Theme by Arcsin modified by Vokiel