ILoveYAnny
@ILoveYAnny

Как не допустить повторение данных в MySQL при ORDER by rand() LIMIT $limit,10?

Здравствуйте, мне нужно получать по 10 случайных строк из БД, при этом не допустить их повторения, как это сделать правильно?
  • Вопрос задан
  • 468 просмотров
Решения вопроса 1
@Sayonji
На SQL:
Я думаю, что для ваших целей сгодится псевдослучайная перестановка.
Шаг 1: Сохраните длину таблицы, пусть $N.
Шаг 2: Выбирите большое (больше $N) число $P, взаимопростое с $N. Это можно сделать с помощью алгоритма для генерации простых чисел.
Шаг 3: Пусть (Q) это запрос, который возвращает нужные вам данные из таблицы, а также поле rownum, являющееся номером строки соответствующей записи. Тогда теперь вы можете сделать так:
SELECT * FROM (Q) ORDER BY $P * rownum % $N LIMIT $limit, 10;

Не на SQL:
Шаг 1: Сгенерируйте случайную перестановку заранее, пусть она будет в массиве $perm, сохраните ее в сессию или еще куда-то.
Шаг 2: Выберите нужные индексы:
$indices = array_slice($perm, $limit, 10);
$indices = join(", ", $indices);
Шаг 3: Запрос: SELECT * FROM (Q) WHERE rownum IN ($indices)

Если хочется без подзапроса, дающего номера строк, то придется запоминать первичные ключи уже возвращенных записей и добавлять в конец запроса WHERE id_key NOT IN (...).

UPD Еще подход, попроще.

Запрос такой:
"SELECT * FROM table ORDER BY func(id_key) LIMIT $limit, 10;"
Здесь func это некоторая функция, преобразующая первичный ключ случайным обзром (он ведь числовой?). Например, подойдет $P * id_key % $T, где $P это большое случайное нечетное число, сгенерированное заранее, а $T это степень двойки большая последнего id_key.
Например, подойдет
$T = 2^31;
$P = (rand(2^26, 2^30) - 1) * 2 - 1;
Запрос будет такой:
"SELECT * FROM thetable ORDER BY CAST(id_key AS BIGINT) * $P % $T LIMIT $limit, 10;"

Это даст около миллиарда различных вариантов перемешивания.

В случае, если в таблицу будет добавлена новая запись, или удалена старая, все эти варианты (кроме запоминания уже вышедших айдишников) могут дать сбой, а именно попадание одной старой записи в выборку еще раз.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы