Этого можно добиться с помощью хранимой процедуры. Этот выбирает случайные строки во временную таблицу, пока не будет вставлено нужное количество строк. Если в исходной таблице достаточно строк, во временную таблицу вставляется только одна вставка из случайных строк, достаточных для удовлетворения запроса. Если нет, все содержимое таблицы вставляется во временную таблицу достаточно раз, чтобы заполнить ее. Например, при выборе 20 случайных записей из таблицы, содержащей только 8 строк, он вставит все 8 строк таблицы (в случайном порядке) во временную таблицу, затем снова все 8 строк (в другом случайном порядке) и затем, наконец, 4 случайных ряда. Затем возвращается все содержимое временной таблицы.
DELIMITER //
DROP PROCEDURE IF EXISTS select_random //
CREATE PROCEDURE select_random (IN tablename VARCHAR(256), IN numrows INT)
BEGIN
DECLARE rowcnt INT DEFAULT numrows;
SET @q = CONCAT('CREATE TEMPORARY TABLE random LIKE ', tablename);
PREPARE stmt FROM @q;
EXECUTE stmt;
SET @q = CONCAT('SELECT COUNT(*) INTO @totrows FROM ', tablename);
PREPARE stmt FROM @q;
EXECUTE stmt;
REPEAT
SET @q = CONCAT('INSERT INTO random SELECT * FROM ', tablename, ' ORDER BY RAND() LIMIT ', LEAST(@totrows, rowcnt));
PREPARE stmt FROM @q;
EXECUTE stmt;
SET rowcnt = rowcnt - @totrows;
UNTIL rowcnt <= 0
END REPEAT;
SELECT * FROM random;
DROP TABLE random;
END
//
CALL select_random('table_name', 20);