У меня есть таблица itemproperties , из которой я хочу захватить случайную itemproperty , однако я хочу, чтобы случайность ее больше ориентировалась на некоторые свойства товара, чем другие.
Для этого я установил столбец « редкость», в котором хранится информация о том, как часто этот элемент должен отображаться (более высокий = чаще), а один называется rarity_position , который настроен с использованием этого запроса:
SET @i:=0;UPDATE itemproperty SET rarity_position = @i:=@i+rarity;
Это дает следующие результаты:
Затем, чтобы захватить случайное значение, я подумал, что буду использовать:
SELECT * FROM itemproperty WHERE id = ( SELECT id FROM itemproperty WHERE rarity_position >= FLOOR ( RAND()* ( SELECT MAX(rarity_position) FROM itemproperty ) ) ORDER BY rarity_position ASC LIMIT 1 ) LIMIT 1
Чтобы выбрать случайное число с максимальным значением rarity_position, возьмите itemproperty с rarity_position, которое находится чуть выше этого.
В большинстве случаев это работает так, как ожидалось, однако примерно в третий раз результаты не возвращаются.
Возможно, соответствующая информация о сервере:
Software: MySQL Software version: 5.0.95-log - MySQL Community Server (GPL) Protocol version: 10 Server charset: UTF-8 Unicode (utf8)
Вы можете воспроизвести поведение этой модели:
create table itemproperty ( id int, rarity int, rarity_position int ); insert into itemproperty values ( 1, 50, 50 ), ( 2, 50, 100 ), ( 3, 50, 150 ), ( 4, 50, 200 ), ( 5, 50, 250 ), ( 6, 50, 270 ), ( 7, 50, 320 ), ( 8, 50, 370 ), ( 9, 50, 420 ), ( 10, 50, 470 ), ( 11, 50, 520 ) ;
Если вы пытаетесь выполнить только подзапрос, он работает каждый раз:
SELECT id FROM itemproperty WHERE rarity_position >= FLOOR ( RAND()* ( SELECT MAX(rarity_position) FROM itemproperty ) ) ORDER BY rarity_position ASC LIMIT 1
Но если вы инкапсулируете его в:
SELECT * FROM itemproperty WHERE id = ( // here the above request ) LIMIT 1;
Он не будет работать так, как ожидалось.
Что заставляет его не возвращать никаких результатов каждый раз?
SELECT * FROM itemproperty ORDER BY RAND() * rarity DESC LIMIT 1
Нашел работоспособное решение, подобное методу zerkms:
ORDER BY -LOG(1.0 – RAND()) / rarity
Источник
Примечательно, что недостающие части выглядят так, как будто они могут быть связаны с этим вопросом: запрос MySQL с условием подзапроса RAND ()
Я предполагаю, что RAND () в ГДЕ вызывает некоторую странность.