基本上我正在尝试创建某种“算法”来从表中选择行。
想象一下,你有一个装满 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`
}
答案 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]
在示例中,3
和7
被选为&#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)
请注意,对于大数据集,这将非常缓慢,但对于理智的行数,它仍然适用。