Как стать автором
Обновить

Комментарии 17

Это называется — «нечего делать? Собери велосипед!»

Первая ссылка из гугла по запросу «mysql rand приоритет»
www.sql.ru/forum/actualthread.aspx?tid=323828

Вкратце:
… ORDER by (RAND()*priority_column)
А если 100 000 элементов и нужно выбрать одну запись — для всех RAND генерировать?
Для количества объектов, что указал ТС, это нормально.
я указал только пример, глупо было бы писать 100 000 объектов для примера… вы господин очень буквально все понимаете
Допустим.

Про велосипед. В том же мускульном мануале где-то говорится, что типа если вам нужно выбрать одну запись из огромного числа, лучше сгенерируйте номер айдишника и запросите его напрямую.

Решение ТС наводит на размышления, не такой уж велосипед.
Если в БД 100 000 элементов и вы будете использовать вариант предложенный ТС-ом, то сервер точно лопнет
ок мистер умник, а если база данных не mysql и объекты просто находятся в системе??? Или даже если база и есть, но база не умеет?
Гляда на такие комменты вспоминается отрывок из Звездного пути, где Арчера забросило в будующее после глобальной войны и все разрушено. И они пытались создать какуюто штуку для передачи данных в прошлое. Там прозвучала такая фраза «Зачем мне было знать его устройство, в наше время они на каждой парте стоят».

Да круто что ты знаешь что есть такая функция, а ты знаешь как она работает?
Прекрасно знаю. При написании комментария опирался на то, что вы указали субд mysql.
я указал что мне не хотелось брать какоето решение, потому что я использовал mysql. Извиняюсь если ввел в заблуждение. Тем не менее, здесь обсуждаются алгоритмы на сколько я понял
О том, что такое случайная величина и как получить требуемое распределение из равномерного рассказывают на лекциях по теории вероятности. В любом случае построить отрезок из интервалов, соответствующих коэффициенту ротации, и взять rand() на этом отрезке проще, чем городить массивы. Причём можно сделать так, что при показе баннера надо будет сделать только 2 запроса, и оба по PK. Апдейтить коэффициенты, правда, будет чуть сложнее. По сложности можно уложиться в log(n), так что 100 000 записей не страшно.

Ещё один вариант — построить индекс по полю коэффициента, а коэффициенты хранить в виде суммы всех предыдущих + коэффициент текущей записи. Тогда 1 запрос даёт максимальный коэффициент (это 1 проход по индексу), потом запрос типа where k > rand(max_k) limit 1 ещё раз пройдётся по индексу и вернёт нужную запись. Сложность этого алгоритма log(n) (т.к. есть индексы, а индексы — деревья), что вполне приемлемо. Удалять записи опять будет немного сложно, зато вся логика в базе.
немного не понял часть where k > rand(max_k) limit 1… первым запросом мы же просто берем максимум… тоесть получается k > max_k или я что то не догнал?
Нет. Коэффициент ротации надо хранить в виде верхней границы, т.е.:
name      k_orig   k
banner1   10       10
banner2   10       20
banner3   20       40
banner4   10       50


У баннеров 1,2 и 4 в этом случае коэффициент ротации 10, а у баннера 3 — 20. Из неудобств: при удалении баннера или изменении коэффициентов надо будет пересчитывать цифирки. Из удобств: работать будет быстро. Если куда нибудь ещё кэшировать максимум — то совсем быстро будет работать, за log(n).

В синтаксисе MySQL rand() должен выглядеть так:
SELECT * FROM banners where k < FLOOR(RAND() * (max_k + 1));


Можно хранить нижнюю границу и тогда сравнивать k > ...., не суть важно, на скорость не влияет.
А можно просто нагенерить в таблицу очередь, в которой будут воспроизводиться банеры. И последовательно выбирать следующий элемент. Тех банеров которых больше можно чаще вставить в эту очередь.
А случайность в такой выборке может быть и не нужна, пользователи своими запросами сами ее создадут (в случае если пользователей все же больше одного).
это собственно и есть мой второй вариант. Просто без последнего рандома.

И хватит уже обсуждать это банерами. Абстрагируйтесь. На самом деле я писал это далеко не для банеров
По тексту понял что вы сначала выбираете ротационную таблицу, а затем достраиваете массив дублями объектов в зависимости от рейтинга.
Я же предлагаю сразу в качестве ротационной таблицы хранить очередь показов со всеми дублями, и выбирать последовательно элементы, возложив рандомизацию на плечи пользователей.
Если что-то не так понял в вашей статье — прошу извинить.
немного не так. Я описал два разных способа: 1- это ротационная таблица, куда записывается сумма понижающих формул. 2- непосредственно решение через массив с дубликатами. В принципе если задуматься смысл у обоих методов одинаков. Разная только реализация.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории