使用`rand()`和`having`

Eri*_*k S 10 mysql mariadb

我有一个包含记录列表的表.每次迭代时,必须从特定偏移量开始随机选择这些迭代.每行都有机会被挑选(因此,例如新的或不经常挑选的行被挑选更多).

但是,某些东西不起作用,导致返回的行不满足使用别名的条件rand().

我正在尝试使用以下查询:

select
    id,
    probability,
    rand() rolledChance
from records
where id > :offset
having rolledChance < probability;
Run Code Online (Sandbox Code Playgroud)

其中:offset是预准备语句参数,并且是此用户上次迭代中的最后一次扫描ID.

在这样创建的表上(这是表的相关子集):

CREATE TABLE records (id INT, probability FLOAT);
Run Code Online (Sandbox Code Playgroud)

其中概率是表中0到1之间的值records.但是,这会返回条件不满足的行.我用以下查询检查了这个:

select
    *,
    x.rolledChance < x.probability shouldPick
from
    (select
        id,
        probability,
        rand() rolledChance
    from records
    having rolledChance < probability
) x;
Run Code Online (Sandbox Code Playgroud)

返回的几行是:

id      probability     rolledChance            shouldPick
12      0.546358        0.015139976530466207    1
26      0.877424        0.9730734508233829      0
46      0.954425        0.35213605347288407     1
Run Code Online (Sandbox Code Playgroud)

当我按如下方式重新调整第二个查询时,它按预期工作,只返回rolledChance实际低于的行probability:

select
    *,
    x.rolledChance < x.probability shouldPick
from
    (select id, probability, rand() rolledChance from records) x
where rolledChance < probability;
Run Code Online (Sandbox Code Playgroud)

那我错过了什么?是否probabilityrolledChance我在比较中使用的不同?rand()每次在同一查询中使用别名时是否进行评估?

版本输出:mysql Ver 15.1 Distrib 10.0.28-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2在Debian Jessie上运行.

Jon*_*ske 2

我认为问题在于 HAVING 在 GROUP BY 之后应用,但仍在 SELECT 阶段之前。我意识到这很令人困惑,因为 HAVING 子句引用了 SELECT 语句中的列,但我认为它基本上只是执行 SELECT 语句中的任何内容两次 - 一次用于having,然后再次执行 SELECT。

例如,请参阅这个答案

请注意,这尤其令人困惑,因为如果您引用未出现在 HAVING 子句中的 SELECT 语句中的列名,则会引发错误。

例如,这个小提琴

但根据上面的小提琴,它仍然可以让您根据未出现在输出中的函数的结果进行实际过滤。长话短说,HAVING 子句仍然可以执行您想要的操作,但是您不能使用该方法同时过滤随机值并显示它。如果需要这样做,则需要先使用子查询来修复该值,然后外部查询可以对其进行过滤和显示。

另外,为了明确起见,可能值得在having子句中使用RAND(),而不是在SQL部分。尽管我知道这个问题是在问为什么要这样做,而不是试图具体解决问题。