我有一个包含记录列表的表.每次迭代时,必须从特定偏移量开始随机选择这些迭代.每行都有机会被挑选(因此,例如新的或不经常挑选的行被挑选更多).
但是,某些东西不起作用,导致返回的行不满足使用别名的条件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)
那我错过了什么?是否probability和rolledChance我在比较中使用的不同?rand()每次在同一查询中使用别名时是否进行评估?
版本输出:mysql Ver 15.1 Distrib 10.0.28-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2在Debian Jessie上运行.
我认为问题在于 HAVING 在 GROUP BY 之后应用,但仍在 SELECT 阶段之前。我意识到这很令人困惑,因为 HAVING 子句引用了 SELECT 语句中的列,但我认为它基本上只是执行 SELECT 语句中的任何内容两次 - 一次用于having,然后再次执行 SELECT。
例如,请参阅这个答案。
请注意,这尤其令人困惑,因为如果您引用未出现在 HAVING 子句中的 SELECT 语句中的列名,则会引发错误。
例如,这个小提琴
但根据上面的小提琴,它仍然可以让您根据未出现在输出中的函数的结果进行实际过滤。长话短说,HAVING 子句仍然可以执行您想要的操作,但是您不能使用该方法同时过滤随机值并显示它。如果需要这样做,则需要先使用子查询来修复该值,然后外部查询可以对其进行过滤和显示。
另外,为了明确起见,可能值得在having子句中使用RAND(),而不是在SQL部分。尽管我知道这个问题是在问为什么要这样做,而不是试图具体解决问题。