Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > Выбор случ. строки из БД без повторения для клиент


Автор: Win MK 32 8.5.2009, 17:02
Нужно выбирать из бД случайную строку, но только без посторений. То есть надо засчет сессий запоминать какие строки БД уже были запрошены из браузера. Вот на чем я остановился:

Код

function ask_question(){
    global $db;
    $maxId = mysql_result($db->query("SELECT MAX(qid) FROM questions"),0);
    
    $_SESSION['counter'] = 0;
    
    if(!isset($_SESSION['checked'])){ $_SESSION['checked'] = array(); }
    
    do{
        $rand = rand(1,$maxId); // <========================Ошибка в этой строке
        $_SESSION['checked'][] = $rand;
    }while( (in_array($rand,$_SESSION['checked'])) && ($_SESSION['counter']<=$maxId) );
    
    $r = $db->query("SELECT * FROM questions WHERE qid=".$rand." LIMIT 1");
    
    while($q = mysql_fetch_assoc($r)){
        $_SESSION['counter']++;
        //echo $_SESSION['counter']." ";    
        echo $q['qtext']."<br />";
        echo "[<a href='/?qid=".$q['qid']."&value=1'>Да</a>] ";
        echo "[<a href='/?qid=".$q['qid']."&value=0'>Нет</a>]";
    }
}


И вот какую я ошибку получаю:
Цитата
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 16 bytes) in Z:\home\expert\3\class.php on line 153

Автор: enof 8.5.2009, 17:31
Перевести ошибку никак? Нехватает памяти скрипту, так как не с изображениями и ни с чем прожорливым работа не ведется, значит где-то косяк.
При внимательном просмотре обнаружим бесконечный цикл. А бесконечный он, потому что забыто инкрементирование счетчика.



Просмотрел темы тс.Интересно, в этот раз хотя бы отпишется, решилась ли проблема? На "спасибо" уже и не стоит надеяться.

Автор: bars80080 8.5.2009, 17:46
цикл видать бесконечный $_SESSION['counter'] видать всегда <= $maxId

Добавлено через 44 секунды
вот задержки, млин

Автор: Win MK 32 8.5.2009, 18:10
По "спасибо" пройдусь, прошу прощения.

А комент мне не помог, перевести ошибку я и сам могу равно как и догадаться что где-то (фиг его знает где) есть бесконечный цикл. Если бы я мог анализировать ошибку точнее, я бы не создал бы эту тему.

Автор: enof 8.5.2009, 18:17
Цитата(bars80080 @  8.5.2009,  18:46 Найти цитируемый пост)
$_SESSION['counter'] видать всегда <= $maxId
Цитата(Win MK 32 @  8.5.2009,  18:02 Найти цитируемый пост)

    $_SESSION['counter'] = 0;
    do{
        $rand = rand(1,$maxId); // <========================Ошибка в этой строке
        $_SESSION['checked'][] = $rand;
        $_SESSION['counter']++; // <====== Вот здесь наверное нужно увеличивать счетчик.
    }while( (in_array($rand,$_SESSION['checked'])) && ($_SESSION['counter']<=$maxId) );



Автор: ksnk 8.5.2009, 18:22
Мысль есть - не запоминать показанные топики вообще. Запомнить только некое число, по которому можно воспроизвести всю последовательность и порядковый номер последней показанной записи.
для примера 
-- в сессии будем запоминать некий $seed для "посеивания" случайного числа srand'ом. Если его нету - мы его случайно придумаем
-- последовательность генерируется методом $record[rand(0,$max_counter)], где max_counter - количество всех записей.
-- уже показанные записи - пропускаются. осталось только в процессе "перелистывания" запоминать номера предыдущих записей, чтобы rand не сгенерировал уже показанную...

Понятно, что такое чудо будет работать только для "статических" списков сообщений. если кто-то что-то изменил/добавил - придется сбрасывать сиды со счетчиками.

Автор: Win MK 32 15.5.2009, 19:06
Всем спасибо. Проблему решил.


ksnk, не понял механизма и идеи. Можно объяснить для новичка? smile

Автор: ksnk 15.5.2009, 23:07
Win MK 32, Ну, представим, что мы придумали некое число NNN. 
Делаем srand(NNN) и все результаты функции rand после этого будут одинаковыми. Таким образом, у нас одним числом задается целая последовательность чисел.
Проверка 
Код

$seed=123445678;
$arr=array();
srand($seed);
for($i=0;$i<1000;$i++) $arr[]=rand(0,1000);
print_r($arr);

Итого, первая "случайная строка" будет с индексом $arr[0], вторая $arr[1] и так далее.  Если юзер посмотрел 25 строчек и желает 26-ю, то мы просто "отматываем" на rand'ом 25 позиций и получаем следующую. Проблема только в проверке на то, чтобы такое число еще не встречалось ранее.

Итого, нужно запоминать только порядковый номер уже показанной строки и этот самый $seed.

Автор: Win MK 32 16.5.2009, 15:11
ksnk, спасибо, я не знал про такое. Очень удобно smile


Цитата(ksnk @  15.5.2009,  21:07 Найти цитируемый пост)
то мы просто "отматываем" на rand'ом 25 позиций и получаем следующую. 

Отмытываем циклом? Или есть сразу функция, чтобы получить случайное 25 там число на основе известного $seed?

Автор: ksnk 16.5.2009, 15:20
Win MK 32, Ну да, циклом. Могут возникнуть проблемы, когда придется отмотать 10000 раз smile Но, не очень большие...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)