MySQL поиск на основе round(1 + rand() * x) дает NULL и множественные результаты

Я пытаюсь выбрать имена из таблицы поиска случайным образом в MySQL, чтобы создать тестовый набор данных. У меня есть таблица с 200 именами, полами и идентификатором строки от 1 до 200. Примерно так:

id   firstname   gender
1    Aaron       m
2    Adam        m
3    Alan        m
etc...

Я выбираю из этой таблицы, используя генератор случайных чисел со следующим запросом:

SELECT id, firstname FROM firstname WHERE id = round(1 + (rand() * 199));

Я ожидаю, что случайное число совпадет с ровно одним идентификатором из таблицы поиска, таким образом, получая единичные результаты, такие как

id   firstname
43   Jason

Запуск кода снова и снова вместо этого дает мне выбор

  • одиночные строки (как указано выше)
  • или несколько строк, как

id firstname 29 Ethan 147 Jean

  • или нет результатов (просто NULL в обоих полях).

Если я запускаю генератор случайных чисел самостоятельно, он всегда будет генерировать число от 1 до 200. Как вы можете видеть ниже, поле id равно INT, и запрос ведет себя так же, если я приведу результат как SIGNED. Я также попытался использовать FLOOR вместо ROUND, просто чтобы посмотреть, работает ли это по-другому - увы, нет.

Кто-нибудь может рассказать, почему аномалия? Что мне не хватает?

Вот некоторый код для создания первых 20 строк исходной таблицы в целях тестирования:

-- First Name --
drop table if exists firstname;

  CREATE TABLE firstname (
  id INT NOT NULL,
  firstname VARCHAR(20) NOT NULL,
  gender VARCHAR(1) NOT NULL,
  PRIMARY KEY (id),
  UNIQUE (firstname)
  );

  INSERT INTO firstname
  (id,firstname,gender)
  VALUES
  (1,"Aaron","m"),
(2,"Adam","m"),
(3,"Alan","m"),
(4,"Albert","m"),
(5,"Alexander","m"),
(6,"Andrew","m"),
(7,"Anthony","m"),
(8,"Arthur","m"),
(9,"Austin","m"),
(10,"Benjamin","m"),
(11,"Billy","m"),
(12,"Bobby","m"),
(13,"Brandon","m"),
(14,"Brian","m"),
(15,"Bruce","m"),
(16,"Bryan","m"),
(17,"Carl","m"),
(18,"Charles","m"),
(19,"Christian","m"),
(20,"Christopher","m");

1 ответ

Решение

Поскольку RAND() не является детерминированным, условие WHERE оценивается / выполняется один раз для каждой строки. Таким образом, каждый ряд может быть выбран на 1/199. Вместо этого вы можете использовать подзапрос в предложении FROM (производная таблица), чтобы сгенерировать ровно одно случайное число:

SELECT f.id, f.firstname
FROM firstname f
JOIN (SELECT floor(rand()*200)+1 as rnd) r ON r.rnd = f.id
Другие вопросы по тегам