• Главная
  • » SQL
  • » выбрать 10 случайных, уникальных записей

#1 2015.08.24 19:51

koji
Участник
Зарегистрирован: 2014.07.13
Сообщений: 72
Карма: 3
Профиль

выбрать 10 случайных, уникальных записей

Как можно провести такую выборку? Поиск выдает решение ORDER BY RAND() однако, говорят, что это сказывается на производительности.

Неактивен

#2 2015.08.24 22:49

Gemorroj
Administrator
Откуда: Белоруссия
Зарегистрирован: 2007.11.03
Сообщений: 6586
Карма: 108
Профиль Веб-сайт

Re: выбрать 10 случайных, уникальных записей

сказывается. но если у тебя БД не 1.000.000 записей, то забей и используй order by rand. т.к. иные решения чересчур черезжопные.

Неактивен

#3 2015.08.24 23:11

koji
Участник
Зарегистрирован: 2014.07.13
Сообщений: 72
Карма: 3
Профиль

Re: выбрать 10 случайных, уникальных записей

Gemorroj, сделал набросок через multi_query и php, но мне бы получать как-то уникальный rand. Может имеется у тебя?
так:
запрос кол-ва записей в бд;
генерация 10 чисел из этого диапазона при помощи PHP rand();
генерация в цикле 10 запросов с этими случайными числами, т.е. их подстановка;
запрос через multi_query

Неактивен

#4 2015.08.25 08:11

koji
Участник
Зарегистрирован: 2014.07.13
Сообщений: 72
Карма: 3
Профиль

Re: выбрать 10 случайных, уникальных записей

Не знаю как производить дополнительную генерацию rand внутри if (in_array($rand, $random)) до тех пор пока не выпадет уникальное число.
Еще можно нарандить 100 чисел и пропустить их через array_unique.
Как быть, Gemorroj, пожалуйста, доведи до ума.

Код:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?
 
$row[0] = 20; // суммарное кол-во записей в БД
$random = [];
$match = 0;
 
      for ($i = 1; $i <= 10; $i++)
      {
        $rand = (string) rand(1, $row[0]);
 
        if (in_array($rand, $random))
        {
          // если есть совпадение запускаем rand еще раз
          $rand  = (string) rand(1, $row[0]);
          $match += 1; // узнать кол-во совпадений
        }
        $random[$i]   = $rand; // массив уникальных чисел
      }
 
 
 
echo      var_dump($random) . '<br>';
echo      $match . '<br>';
 
?>

Неактивен

#5 2015.08.25 08:36

koji
Участник
Зарегистрирован: 2014.07.13
Сообщений: 72
Карма: 3
Профиль

Re: выбрать 10 случайных, уникальных записей

Какая вероятность что из 50 random чисел не окажется 10 уникальных? Этот вариант тоже подходит, но его нельзя масштабировать. Чем больше диапазон требуемых уникальных чисел тем больше потребуется генерировать случайных и медленнее будет работать.

Код:

1
2
3
4
5
6
7
8
9
10
11
12
13
$row[0] = 20; // суммарное кол-во записей в БД
 
for ($i = 1; $i <= 50; $i++)
{
$rand[] = rand(1, $row[0]);
}
 
$unique = array_unique($rand); // здесь еще бы ключи переписать последовательно: 0 1 2 3 4 5 6 7...
 
for ($i = 1; $i <= 10; $i++)
{
echo $unique[$i] . ', ';
}

Неактивен

#6 2015.08.25 09:26

Gemorroj
Administrator
Откуда: Белоруссия
Зарегистрирован: 2007.11.03
Сообщений: 6586
Карма: 108
Профиль Веб-сайт

Re: выбрать 10 случайных, уникальных записей

я так и не понял чем не подошел order by rand

Неактивен

#7 2015.08.25 09:39

koji
Участник
Зарегистрирован: 2014.07.13
Сообщений: 72
Карма: 3
Профиль

Re: выбрать 10 случайных, уникальных записей

Gemorroj, совесть сожрет. Альтернатива в 2 минутах.. через multi_query

Неактивен

#8 2015.08.25 11:25

tipsun
Moderator
Зарегистрирован: 2009.10.14
Сообщений: 2291
Карма: 19
Профиль

Re: выбрать 10 случайных, уникальных записей

koji, а нельзя сделать типа: сгенерировать 1 случайное число и ограничить кол-во записей LIMIT 10.
А чтоб не получилось так, что не хватает записи при 100 записях в базе и сгенерило случ. число 95, сделать -10 у получаемого рандомного числа.
Записи будут только идти подряд, но будут уникальными и своего рода тоже рандомными smile
- - - -
Во всех остальных случаях тебе все равно надо обращаться к базе с COUNT(), чтоб узнать текущее кол-во записей, вложить в функцию, возможно свою, чтоб получить 100% рандомных 10 чисел, снова отправить запрос в базу, вытащить запрос.
Добавлено спустя   6 минут  24 секунды:
Вот ещё на хабре пишут про оптимизацию:
- http://habrahabr.ru/post/55864/
- http://habrahabr.ru/post/54176/
- http://habrahabr.ru/post/54176/#comment_1444785

Неактивен

#9 2015.08.25 11:44

koji
Участник
Зарегистрирован: 2014.07.13
Сообщений: 72
Карма: 3
Профиль

Re: выбрать 10 случайных, уникальных записей

tipsun, не совсем понял, что рекомендуешь на словах. Благодарю за хабра-ссылки, надо бы замерить скорость.

Неактивен

#10 2015.08.25 11:48

tipsun
Moderator
Зарегистрирован: 2009.10.14
Сообщений: 2291
Карма: 19
Профиль

Re: выбрать 10 случайных, уникальных записей

koji, ну сгенерировал 1 число (выбрал 1 случайное id/запись) и далее после него цепляешь еще, 9 за ним которые.
Если записи не повторяются, то 100% уникальность гарантирована.
Но они будут идти подряд: типа 51 и цепляешь 52, 53, .., 60
Не знаю, это лишь мысль, как будет с производительностью и все такое..

Неактивен

#11 2015.08.25 12:24

koji
Участник
Зарегистрирован: 2014.07.13
Сообщений: 72
Карма: 3
Профиль

Re: выбрать 10 случайных, уникальных записей

tipsun, а если окажется что в БД выбранное 51 это последняя запись? Хотя это неплохой вариант. Мне кажется в ссылках есть пример (из комментариев) вроде подходит, надо бы попробовать его. Но хочу доделать свой через мульти + php чтобы сравнить скорость.

Неактивен

#12 2015.08.25 12:41

tipsun
Moderator
Зарегистрирован: 2009.10.14
Сообщений: 2291
Карма: 19
Профиль

Re: выбрать 10 случайных, уникальных записей

tipsun написал:

koji, а нельзя сделать типа: сгенерировать 1 случайное число и ограничить кол-во записей LIMIT 10.
А чтоб не получилось так, что не хватает записи при 100 записях в базе и сгенерило случ. число 95, сделать -10 у получаемого рандомного числа.
Записи будут только идти подряд, но будут уникальными и своего рода тоже рандомными smile

Неактивен

#13 2015.08.25 16:44

koji
Участник
Зарегистрирован: 2014.07.13
Сообщений: 72
Карма: 3
Профиль

Re: выбрать 10 случайных, уникальных записей

tipsun, благодарю
Добавлено спустя   5 минут  31 секунду:
При 10646 записях в БД

ORDER BY RAND()
0.014

первый уникальный с последующими за ним числами  (51, 52, 53, 54 и т.д.)
0.003

т.е.

Код:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$query = "
SELECT
id,
data
FROM
files AS r1
JOIN
(SELECT (RAND() * (SELECT MAX(id) FROM files)) AS ids) AS r2
WHERE
r1.id >= r2.ids
ORDER BY
r1.id ASC
LIMIT
10;
";

Неактивен

#14 2015.08.25 17:42

tipsun
Moderator
Зарегистрирован: 2009.10.14
Сообщений: 2291
Карма: 19
Профиль

Re: выбрать 10 случайных, уникальных записей

koji, рандомно взятый кусок списка получается как бы. А мой код лучше не юзай, я там ошибся в нескольких местах, ну нафиг smile

Неактивен

#15 2015.08.25 22:54

koji
Участник
Зарегистрирован: 2014.07.13
Сообщений: 72
Карма: 3
Профиль

Re: выбрать 10 случайных, уникальных записей

tipsun, видимо на скорую руку набросал wink я тоже сомневался
доработал свой кусок, он отлично выбрасывает более 10 уникальных random,
выбираю по ключам в масиве $unique от 0 до 9 а остальное остается (2-5 элементов)

Код:

1
2
3
4
5
for ($i = 1; $i <= 20; $i++)
{
$rand[] = rand(1, 10646);
}
$unique = array_values(array_unique($rand));

вариант из двух: тот, что посоветовал ты и через multi_query. Последний срабатывает за 0.005. Там сгенерировать 10 запросов с выборкой WHERE id = $unique[$i] Надо бы запустить на базе побольше, тогда точно станет ясно.

Отредактировано koji (2015.08.25 23:03)

Неактивен

#16 2015.08.25 23:46

tipsun
Moderator
Зарегистрирован: 2009.10.14
Сообщений: 2291
Карма: 19
Профиль

Re: выбрать 10 случайных, уникальных записей

Gemorroj, что "скажешь"? Мне кажется есть ещё более крутой и оптимизированный способ.
Чисто из "спортивного" интереса сейчас ещё посидел, подумал.
Вот вроде норм вышло, но чем меньше множество, тем больше повторов и больше циклов.
+ фильтры на данные нужны, чтоб записей было более 0 и все такое крч.

Код:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
 
$rand_zapisej 10;
$id_min 1;     // id в базе обычно начинается с 1
$id_max 10646// получаем через базу
 
var_dump($rand_zapisejrandNumbs($rand_zapisej$id_min$id_max));
 
function randNumbs($qty$min$max) {
    $rst = array();
 
    while ($qty) {
        $num rand($min$max);
        if (! $rst[$num]) {
            $qty--;
            $rst[$num] = $num// или: $rst[$num] = null;
            // если null, потом foreach ($array as $key => $valueIsNull) { echo $key; }
            // или array_keys(randNumbs(/* args */));
        }
    }
 
    return $rst;
}

Неактивен

#17 2015.08.26 00:00

tipsun
Moderator
Зарегистрирован: 2009.10.14
Сообщений: 2291
Карма: 19
Профиль

Re: выбрать 10 случайных, уникальных записей

Если кол-во записей совпадает с кол-во выводимых постов, то можно вообще сделать через: shuffle(range(1, 10));
Кстати подряд идущие записи ты прежде чем вывести можешь раскидать в массиве этой функцией: shuffle($array);

Неактивен

#18 2015.08.26 09:25

Gemorroj
Administrator
Откуда: Белоруссия
Зарегистрирован: 2007.11.03
Сообщений: 6586
Карма: 108
Профиль Веб-сайт

Re: выбрать 10 случайных, уникальных записей

tipsun ну у тебя подразумевается что дырок в очередности id в бд нету. а в реальности, записи могут отсутствовать.

Неактивен

#19 2015.08.26 11:51

koji
Участник
Зарегистрирован: 2014.07.13
Сообщений: 72
Карма: 3
Профиль

Re: выбрать 10 случайных, уникальных записей

Gemorroj, точно, да, об этом никто не думал. ID ведь могут отсутствовать.

Неактивен

  • Главная
  • » SQL
  • » выбрать 10 случайных, уникальных записей

Дополнительно

forum.wapinet.ru

PunBB Mod v0.6.1
0.019 s