Случайная строка в MySQL - PullRequest
       7

Случайная строка в MySQL

3 голосов
/ 11 ноября 2011

Я пытаюсь получить случайную строку в MySQL.Вот мой подход:

SELECT * 
FROM users 
WHERE id = 
 (SELECT floor((max(id) - min(id) + 1) * rand()) + min(id)
  FROM users);

Это может вернуть пустой набор, если в идентификаторах есть пробелы.Я в порядке с этим.Однако,

  1. У меня нет пробелов, и я все еще довольно часто получаю пустой набор .
  2. Более тревожно: я получу два или более результата время от времени.

В чем причина этого странного поведения?Как, я правильно понял?

Примечание:

  • стол довольно большой (10 ^ 6 ... 10 ^ 7);Я не могу использовать ни одно из очевидных и известных решений, основанных на случайном порядке или даже на использовании count () .
  • Я застрял сMySQL, мне все равно, как это делается на стороне клиента ruby ​​/ PHP / что угодно.
  • Я пытался приводить плавающие типы, но это не помогло.
  • Соответствующий вариант PostgreSQL (случайный вместо rand и некоторых типов типов) работает нормально.

Ответы [ 5 ]

2 голосов
/ 11 ноября 2011

Я подозреваю, что это потому, что RAND() оценивается для каждой строки в таблице USERS в основном запросе.Я предлагаю:

SELECT u1.* 
from users u1,
     (SELECT floor((max(id) - min(id) + 1) * rand())  + min(id) lid from users) u2
WHERE u1.id > u2.lid
LIMIT 1
1 голос
/ 12 ноября 2011

Это позволяет избежать повторной оценки random() во время агрегации и также должно быть быстрее, поскольку min(id) и random() оцениваются только один раз.

SELECT u.* 
FROM   users u
      ,(SELECT min(id) AS min_id, max(id) AS max_id FROM users) x
WHERE  u.id > (floor((x.max_id - x.min_id + 1) * rand()) + x.min_id)
LIMIT  1;
1 голос
/ 11 ноября 2011

Попробуйте это -

SELECT t.* FROM
  users t,
  (SELECT @id := (FLOOR((MAX(id) - MIN(id) + 1) * RAND()) + MIN(id)) FROM users) t2
WHERE
  t.id = @id;
0 голосов
/ 11 ноября 2011

Как насчет:

SELECT * 
FROM users 
WHERE id >= (SELECT floor((max(id) - min(id) - 1) * rand())  + min(id) from users)
LIMIT 1

или подобное?

В значительной степени это должно ограничить вас одним результатом, и если он попадет в пробел (каким-то образом), то он просто возьмет следующий доступный.

0 голосов
/ 11 ноября 2011
SELECT * FROM users ORDER BY rand() limit 1;

Вернет случайную строку.

...