За последние 24 часа нас посетил 49861 программист и 1689 роботов. Сейчас ищут 1073 программиста ...

Выбор случайной строки из таблицы

Тема в разделе "MySQL", создана пользователем krow7, 29 авг 2012.

  1. krow7

    krow7 Активный пользователь

    С нами с:
    12 авг 2009
    Сообщения:
    398
    Симпатии:
    0
    Адрес:
    из Азии
    Всем ку :)
    Нужно выбрать случайную строку из таблицы. Структура такова: 3 поля (id, source, num). id идет без дырок подряд.
    Пробовал вот такую здоровенную конструкцию:
    Код (Text):
    1.  
    2. SELECT * FROM `stories` WHERE `source`='sram' AND `num`=((SELECT MIN(id) FROM `stories` WHERE `source`='sram') + ((SELECT COUNT(*) FROM `stories` WHERE `source`='sram') * RAND()));
    т.е. берем минимальный id для этого source + число элементов с этим source * RAND().
    А он мне эррор.
    Подскажите, правильно ли я вообще копаю и как реализуется выбор случайной строки из базы.
     
  2. Goryn

    Goryn Активный пользователь

    С нами с:
    4 апр 2006
    Сообщения:
    398
    Симпатии:
    0
    Адрес:
    Ярославль
  3. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Хорошая ссылка. Хочется добавить, что в реале скорее выборка может понадобиться не совсем случайная. Т.е. для посетителя она будет выглядеть случайной, но мы то лучше знаем что стОит показывать ;)
    Например есть галерея с миллионами фотографий, но в ротации "случайных" кадров интереснее видеть те, что опубликованы или комментировались не более недели назад. Или имеют хороший рейтинг. Т.о. мы сокращаем область определения до разумных величин, которые реально засунуть в кеш. Кеш обновлять, скажем, раз в сутки, а частые выборки будут происходить из кеша мгновенно.
     
  4. krow7

    krow7 Активный пользователь

    С нами с:
    12 авг 2009
    Сообщения:
    398
    Симпатии:
    0
    Адрес:
    из Азии
    За линк и комменты спасибо.
    Только непонятно, почему мой варик не хочет работать. Разве такие запросы строить нельзя?
     
  5. krow7

    krow7 Активный пользователь

    С нами с:
    12 авг 2009
    Сообщения:
    398
    Симпатии:
    0
    Адрес:
    из Азии
    С предыдущим ладно, сделал немного по-другому.
    Есть таблица sram, устройство такое (поля id, num - оба выставил bigint). id идут непрерывно от 1 до много.
    Пытаюсь выбирать случайное значение num так:
    Код (Text):
    1. SELECT * FROM `sram` WHERE `id` = 1 + FLOOR((SELECT COUNT(*) FROM `sram`) * RAND())
    Причем выбирается то две строки, то вообще ни одной. Как так получается? Ведь id в WHERE выбирается единственным образом.
    Отдельно пробовал исполнять
    Код (Text):
    1. SELECT 1 + FLOOR((SELECT COUNT(*) FROM `sram`) * RAND())
    Всегда по одному значению, а когда полный запрос - ерунда какая-то. Где я провафлил, подскажите, пожалуйста, умные головы :)
    P.S. Вывод проверял таким кодом:
    Код (PHP):
    1. <?php
    2. $m = new mysqli('localhost', 'root', '1234', 'sram');
    3. for($i = 1; $i <= 100; $i++)
    4. {
    5.     $result = $m->query("SELECT * FROM `sram` WHERE `id` = 1 + FLOOR((SELECT COUNT(*) FROM `sram`) * RAND())");
    6.     $row = $result->fetch_all();
    7.     print_r($row);
    8.     $result->free();
    9. }
    10. $m->close(); 
    Вывод(часть):
    Код (Text):
    1. Array
    2. (
    3.     [0] => Array
    4.         (
    5.             [0] => 1951
    6.             [1] => 10370
    7.         )
    8.  
    9.     [1] => Array
    10.         (
    11.             [0] => 2210
    12.             [1] => 11464
    13.         )
    14.  
    15.     [2] => Array
    16.         (
    17.             [0] => 3660
    18.             [1] => 17617
    19.         )
    20.  
    21. )
    22. Array
    23. (
    24. )
    25. Array
    26. (
    27.     [0] => Array
    28.         (
    29.             [0] => 3795
    30.             [1] => 18406
    31.         )
    32.  
    33.     [1] => Array
    34.         (
    35.             [0] => 4472
    36.             [1] => 21359
    37.         )
    38.  
    39. )
    40. Array
    41. (
    42.     [0] => Array
    43.         (
    44.             [0] => 2512
    45.             [1] => 12675
    46.         )
    47.  
    48.     [1] => Array
    49.         (
    50.             [0] => 4699
    51.             [1] => 22171
    52.         )
    53.  
    54. )
     
  6. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    условие в твоем WHERE вычисляется столько раз, сколько у тебя строк в sram. поэтому "истина" может срабатывать сколько угодно раз, от ни одного до всегда )))
    вычисли нужное значение ДО запроса и подставляй готовый результат

    Добавлено спустя 5 минут 4 секунды:
    попробуй так:
    Код (Text):
    1.  
    2. select sram.*
    3. from
    4.   sram,
    5.   (select floor(rand() * max(id)) + 1 as id from sram) as computedonce
    6. where sram.id=computedonce.id
     
  7. krow7

    krow7 Активный пользователь

    С нами с:
    12 авг 2009
    Сообщения:
    398
    Симпатии:
    0
    Адрес:
    из Азии
    Спасибо здоровенское, рандомит на ура :)
     
  8. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    Конечно не желательно в запросе рандомить.
    Ну это уже вы решайте)