RAND()基于特定标准

时间:2014-12-12 12:07:04

标签: mysql

基本上我正在尝试创建某种“算法”来从表中选择行。

想象一下,你有一个装满 650 的人的游泳池,你想要运行一台机器,它会舀下来并抓住 40 ,裸露在记住这些 40 的人,他们在游泳池中的2个人只能很少被抓住。

现在说这是代码术语:

SELECT
    *
FROM
    people
ORDER BY
    RAND()
LIMIT
    40

然后我想在这样的查询中添加某种“算法”,这样做但是在mySQL

$rand = rand(4,100);
if($rand == 26) {
    //the option is now open to potentially scoop those rare people which have the ID of `15256` and `884`
}

1 个答案:

答案 0 :(得分:1)

我会说:一般来说使用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]

的值

在示例中,37被选为&#34;稀有人ID&#34;那些人将以正常概率的1/10出现在结果集中。另外,我选择了LIMIT的3行,您最有可能想要更改这些行。

此外,LEFT JOIN仅用于为ids和其他用过的东西指定一个定义位置。它可以替换为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

请注意,对于大数据集,这将非常缓慢,但对于理智的行数,它仍然适用。