, я видел, что он происходит снова и снова. Разработчики делают это, потому что этот процесс является раздражающим:
, Пессимистическая блокировка чувствует себя подобно любительскому часу, извините.
Попробуйте следующее:
SELECT *
FROM (
SELECT @cnt := COUNT(*) + 1,
@lim := 10
FROM t_random
) vars
STRAIGHT_JOIN
(
SELECT r.*,
@lim := @lim - 1
FROM t_random r
WHERE (@cnt := @cnt - 1)
AND RAND(20090301) < @lim / @cnt
) i
Это особенно эффективно для MyISAM
(поскольку COUNT (*)
мгновенно), но даже в InnoDB
он в 10
раз эффективнее, чем ORDER BY RAND ()
.
Основной идея заключается в том, что мы не сортируем, а вместо этого сохраняем две переменные и вычисляем вероятность выполнения
строки, которая будет выбрана на текущем шаге.
Подробнее см. в этой статье в моем блоге:
Обновление:
Если вам нужно выбрать только одну случайную запись,
Это зависит от того, насколько случайным вы должны быть. Решение, которое вы связали, работает очень хорошо, IMO. Если у вас нет больших пробелов в поле идентификатора, оно все равно будет довольно случайным.
Однако вы сможете сделать это в одном запросе, используя это (для выбора одного значения):
SELECT [fields] FROM [table] WHERE id >= FLOOR(RAND()*MAX(id)) LIMIT 1
Другие решения:
random
, в таблицу и заполнять ее случайными числами. Затем вы можете сгенерировать случайное число в PHP и выполнить «SELECT ... WHERE rnd> $ random»
Вот как бы я это сделал:
SET @r := (SELECT ROUND(RAND() * (SELECT COUNT(*)
FROM accomodation a
JOIN accomodation_category c
ON (a.ac_category = c.acat_id)
WHERE a.ac_status != 'draft'
AND c.acat_slug != 'vendeglatohely'
AND a.ac_images != 'b:0;';
SET @sql := CONCAT('
SELECT a.ac_id,
a.ac_status,
a.ac_name,
a.ac_status,
a.ac_images
FROM accomodation a
JOIN accomodation_category c
ON (a.ac_category = c.acat_id)
WHERE a.ac_status != ''draft''
AND c.acat_slug != ''vendeglatohely''
AND a.ac_images != ''b:0;''
LIMIT ', @r, ', 1');
PREPARE stmt1 FROM @sql;
EXECUTE stmt1;