I сказал бы: использование ORDER BY RAND()
- плохая идея в целом, потому что она будет оказывать огромное влияние на производительность. Это общеизвестный факт, поскольку RAND()
будет оцениваться «на лету» и поэтому не будет использовать индекс для этих значений.
Однако, с теоретической точки зрения, вы можете определить некоторые границы и проверить, существует ли случайно генерируемое значение. Это приведет вас к чему-то вроде:
SELECT
id,
name
FROM
(SELECT
pool.id AS id,
name,
IF(rare_ids.id IS NULL, 1, 1/@probability_divisor) AS probability,
RAND() AS random
FROM
pool
LEFT JOIN
(SELECT 3 AS id
UNION ALL
SELECT 7 AS id) AS rare_ids
ON
pool.id = rare_ids.id
CROSS JOIN
(SELECT @probability_divisor:=10) AS init
) AS struct
WHERE
random<probability
ORDER BY
random
LIMIT 3
(проверьте скрипку here)
Объяснение на этом - это то, что вы определяете некоторый вероятностный делитель, а затем проверить, если случайно сгенерированное значение находится внутри интервала [0 .. 1/divisor]
- это, конечно, зависит от того, что RAND()
является порождающей значения из [0 .. 1]
в образце, 3
и 7
выбраны, чтобы быть «редкие люди иды» и эти люди будут появляться в наборе результатов с 1/10 нормальной PROBA Билити. Кроме того, я выбираю 3 строки с LIMIT
, которые вы, скорее всего, захотите изменить.
Кроме того, LEFT JOIN
был сделан только для указания места определения идентификаторов и других используемых вещей. Он может быть заменен IN
, как:
SELECT
id,
name
FROM
(SELECT
id,
name,
IF(id IN (3, 7), 1/@probability_divisor, 1) AS probability,
RAND() AS random
FROM
pool
CROSS JOIN
(SELECT @probability_divisor:=10) AS init
) AS struct
WHERE
random<probability
ORDER BY
random
LIMIT 3
(с fiddle)
Пожалуйста, обратите внимание, что для больших наборов данных это будет работать очень медленно, но здравомыслящий количество строк она по-прежнему применяется.
Пожалуйста, объясните лучше, что вы пытаетесь сделать. Например, что означает «очень-очень редко». –
@GordonLinoff в простых терминах, у меня есть 2 определенных строки в таблице, которые я не хочу, чтобы RAND() очень часто хватался – Curtis