Вывести 3 рандомных числа из массива

129
26 января 2020, 07:30

У меня есть две таблицы. В одной таблице id пользователей, в другой id пользователей, которых функция рандома не должна вызвать. Надо вывести 3 рандомных не повторяющихся числа из переменной $allowed.

$banned = "SELECT id FROM admin";
$allowed = "SELECT id FROM 10a WHERE id NOT IN (". $banned .")";
Answer 1

Простейший вариант, который судя по названию таблицы 10a (школа?), Вам подойдёт:

SELECT id
FROM 10a
WHERE id NOT IN (SELECT id FROM admin)
ORDER BY RAND()
LIMIT 3

Недостаток этого варианта - логарифмическое замедление при увеличении количества строк в таблице 10a, так как ORDER BY RAND() вызывает сканирование и затем сортировку всей таблицы целиком - и без использования индексов.

Вот здесь и здесь всё это неплохо расписано.

Вариант для больших таблиц, который мне кажется предпочтительным, это вставка в таблицу дополнительного индексированного float столбца rnd, в который при создании строки записывается результат функции RAND(). В этом случае рандомизация выполняется на этапе заполнения таблицы, а при выборке мы случайным образом определяем начальное значение столбца rnd и выполняем чтение нужного количества строк, отсортированных по rnd.

Пример на db-fiddle. Схемы таблиц и запрос - ниже:

CREATE TABLE 10a (
  id INT NOT NULL AUTO_INCREMENT,
  name text,
  rnd float,
  PRIMARY KEY (id)
);
CREATE TABLE admin (
  id INT
);
CREATE TRIGGER 10a_bi
BEFORE INSERT ON 10a
FOR EACH ROW
    SET NEW.rnd = RAND();
CREATE INDEX rnd_idx ON 10a(rnd);

Заметьте, что в запросе 2 раза встречается число 3 - количество возвращаемых значений. Это сделано для того, чтобы "неудачники" с 3 самыми большими значениями rnd имели равновероятный шанс попасть в выдачу, как и все остальные

SELECT r.*
FROM 
( 
    SELECT RAND() * 
    (
        SELECT rnd
        FROM 10a
        WHERE id NOT IN (SELECT id FROM admin)
        ORDER BY rnd DESC
        LIMIT 1 OFFSET 3
    ) start
) init
JOIN 10a r
WHERE r.rnd > init.start
    AND id NOT IN (SELECT id FROM admin)
ORDER BY r.rnd
LIMIT 3;
READ ALSO
Вывод на экран русских символов php

Вывод на экран русских символов php

День добрый! Не могу понять почему при выводе на экран всей строки отображается как должно, а при переборе �? Подскажите в чем дело

140
Utm метка в заявке

Utm метка в заявке

Нужно чтобы в заявке с формы отображалось ключевое слово, по которому пользователь перешел на сайтКто-нибудь знает как реализовать? Обработчик...

118
PHP С помощью чего лучше реализовать работу с датами и временем?

PHP С помощью чего лучше реализовать работу с датами и временем?

Что лучше использовать для решения таких задач в PHP (mysqL):

102