Jeśli masz tabelę, w której znajduje się wiele rekordów i stajesz przed potrzebą wyświetlenie kilku losowych rekordów – na ogół masz problem związany z wydajnym sposobem realizacji zapytania.
Są różne sposoby na rozwiązanie tego problemu. Najprostszy jest oczywiście ORDER BY RAND(), jednak słynie on z tego, że jest straszliwie powolny, zwłaszcza na dużych tabelach.
Inne rozwiązanie to załadowanie listy kluczy podstawowych tabeli do tablicy w pamięci i losowanie po stronie programu. Wykonujemy wprawdzie dwa zapytania zamiast jednego, jednak jest to metoda dużo bardziej wydajna w niektórych przypadkach.
Wymyśliłem dziś inny sposób, dzięki któremu nie musimy skanować całej tabeli w celu wyświetlenia losowych rekordów. Rozwiązanie to jest bardzo proste w realizacji.

Wystarczy, że do tabeli, z której chcemy pobierać rekordy dodamy kolumnę np. random_num, najlepiej wesprzeć ją indeksem.  W kolumnie tej zapisywać będziemy losową liczbę z jakiegoś zakresu (np. 1 do 1000) podczas każdego zapisania obiektu.

Gdy mamy już tabelę wypełnioną  rekordami z losowymi wartościami  w kolumnie random_num (wartość ta oczywiście będzie się powtarzać w przypadku, gdy tabela ma > 1000 rekordów, ale to nie szkodzi), wystarczy wykonać dwa zapytania:

SELECT COUNT(*) AS cnt FROM tabela

… by zliczyć ilość rekordów.  Wynik zapytania załadujmy do zmiennej cnt. W zmiennej limit natomiast zapamiętajmy ilość rekordów, jakie chcemy pobrać. Następnie:

SELECT * FROM tabela ORDER BY random_num OFFSET :offset LIMIT :LIMIT

Pod parametr :offset podstawiamy losową wartość (losowaną po stronie programu) z zakresu 1 do cnt – ilość rekordów, jakie chcemy pobrać, a pod :limit – wartość zmiennej limit.

Wadą tego rozwiązania jest jego „statyczność”, tzn dla każdego wylosowanego offsetu wynik zapytania będzie się powtarzał jeśli offest będzie się powtarzał. Jeśli jednak zawartość Twojej tabeli zmienia się dość często nie jest to problemem. Innym sposobem obejścia tego stanu rzeczy jest wykonywanie co jakiś czas „reindeksacji” kolumny random_num.