Добро пожаловать на сайт <БагБД>, где вы можете задавать вопросы о программировании и разработке на Битрикс и Битрикс24, и получать быстрые и квалифицированные ответы от профессионалов!

Случайный порядок списка пользователей

00 голосов
9
Как вынуть случайного пользователя или нескольких пользователей? Если бы дело касалось инфоблоков, то там есть $arSort = array("RAND"=>""); и дело сделано. А метод CUser::GetList такое не понимает. Может есть способ? Какой-нибудь, как обычно, недокументированный? :?: :?: :?:
спросил 19 Март, 13 от XXeeper (160 баллов)

9 Ответы

00 голосов
Код
$filter = array("RAND"=>"ASC");
(
   
);
$rsUsers = CUser::GetList(($by="personal_country"), ($order="desc"), $filter)
ответил 19 Март, 13 от Lollipopk (660 баллов)
00 голосов
Олег, это вы откуда такое взяли?
А по теме: штатной возможности случайной сортировки нет.
ответил 19 Март, 13 от Delp (7,220 баллов)
00 голосов
Да GetList у CUser очень скромный.
ответил 03 Июнь, 13 от Fka (340 баллов)
00 голосов
Цитата
Олег Іванюк пишет:
Код
$filter = array("RAND"=>"ASC");

(

&nbsp;&nbsp; 

);

$rsUsers = CUser::GetList(($by="personal_country"), ($order="desc"), $filter)


Это не решение. Даже попробовал запустить для спортивного интереса - глупо и не работает. Нельзя писать в фильтр условия сортировки. Они попросту будут пропущены при формировании SQL запроса да и всё.

Ну, буду как-нибудь выкручиваться с этой сортировкой по-другому.
ответил 04 Сен, 13 от XXeeper (160 баллов)
00 голосов
Я бы записал нескольких (или всех) id пользователей в массив, сгенерировал бы случайный ключ массива

Код
$some_key = rand(0, count($array));


и по ключу вытащил бы id пользователя

Код
echo $array($some_key);
ответил 03 Дек, 13 от Lollipopk (660 баллов)
00 голосов
Сейчас на моём сайте 23 тыщи 686 человек... надо выбрать 3 случайных... метод CUser::GetList не имеет возможности сократить кол-во полей в выборке до одного лишь ID.... дальше рассуждения продолжать? :)

Пойду я читать исходный код - как же рандомом выбирают элементы инфоблоков.
ответил 16 Март, 14 от XXeeper (160 баллов)
00 голосов
Если особых фильтраций не нужно, то можно и прямым запросом:

Код
$iUsersCount = 3;

$arUserList = array();
$sSql = 'select ID from b_user where ACTIVE = "Y" and LID = "'.SITE_ID.'" order by RAND('.rand(0, 1000000).') limit 0,'.$iUsersCount;
$dbItems = $GLOBALS['DB']->Query($sSql, false, 'File: '.__FILE__.'<br>Line: '.__LINE__);
while($arItem = $dbItems->Fetch()) {
   $arUserList[] = $arItem['ID'];
}
ответил 07 Июль, 14 от Delp (7,220 баллов)
00 голосов
Большущее спасибо :) Это тоже решение. Правда, у него ограничение - при кол-ве записей больше 100К будет жесткий тормозняк БД. Сам я такое не проверял, но вот при помощи хэлпа по MySQL нашел статью в блоге, где об этом говорится. Там же предлагается иное решение, код которого я привожу ниже.

Ссылка на статью-подсказку: http://www.rndblog.com/how-to-select-random-rows-in-mysql/

Решение проблемы:
Код
//Сколько случайных пользователей мы хотим получить? 
$randUserCnt = 3;
//Получить общее кол-во пользователей
$totalUserCnt = CUser::GetCount();
//Вычисление фракции
$fraction = ($randUserCnt/$totalUserCnt);
//Искусственное приращение фракции для борьбы с плохим генератором при маленькой выборке.
$fractionInc = $fraction*1.8;
if ( $fractionInc < 1)
{
   $fraction = $fractionInc;
}
//Формирование запроса
$myUserRandQuery = 'SELECT ID FROM b_user WHERE RAND() <= '.$fraction.' LIMIT '.$randUserCnt;
echo $myUserRandQuery."<br>";
//Делаем хитрый запрос к БД при помощи готового экземпляра класса CDataBase : $DB
$result = $DB->Query($myUserRandQuery, true);
while ($arRandUser = $result->Fetch())
{//Печать случайных ID пользователей
   echo $arRandUser["ID"]."<br>";
}


Преимущества решения:
+ есть легкое средство борьбы с плохим генератором чисел. Он на любой ЭВМ имеет линейное распределение только при N > 100, т.к. реализовано на ПСЕВДОслучайном алгоритме.
+ способ не грузит БД, т.к. не заставляет её сортировать ничего и подходит для больших объемов данных - более 100 тыс пользователей

Недостатки метода:
- иногда возвращается меньше пользователей, чем было запрошено. Причина - плохой генератор рандома. С этим легко бороться, если делать повтор и "добирать" нехватающих пользователей.


Решение опробовано для случая, когда кол-во пользователей N = 5 и N = ~30K
Результат: пятерка с минусом. :)
ответил 07 Ноя, 14 от XXeeper (160 баллов)
00 голосов
Да, решение действительно более производительное. Спасибо!
ответил 06 Март, 15 от Delp (7,220 баллов)

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

0 голосов
3 ответов
0 голосов
2 ответов
0 голосов
3 ответов
0 голосов
2 ответов
спросил 26 Июнь, 13 от NEEKaLL (160 баллов)
0 голосов
6 ответов
спросил 19 Окт, 13 от Graviti (120 баллов)