我有一个包含记录列表的表。每次迭代时,必须从特定偏移量开始随机选择这些迭代。每一行都有机会被挑选(因此,例如新的或不经常挑选的行被挑选更多)。
但是,某些不起作用,导致返回的行不符合使用别名rand()
的条件。
我试图使用以下查询:
select
id,
probability,
rand() rolledChance
from records
where id > :offset
having rolledChance < probability;
其中:offset
是预准备语句参数,并且是该用户上次迭代中的最后一次扫描ID。
在这样创建的表上(这是表的相关子集):
CREATE TABLE records (id INT, probability FLOAT);
其中概率是表records
上0到1之间的值。但是,这会返回条件不满足的行。我用以下查询检查了这个:
select
*,
x.rolledChance < x.probability shouldPick
from
(select
id,
probability,
rand() rolledChance
from records
having rolledChance < probability
) x;
返回的几行是:
id probability rolledChance shouldPick
12 0.546358 0.015139976530466207 1
26 0.877424 0.9730734508233829 0
46 0.954425 0.35213605347288407 1
当我按如下方式重新调整第二个查询时,它按预期工作,只返回rolledChance
实际低于probability
的行:
select
*,
x.rolledChance < x.probability shouldPick
from
(select id, probability, rand() rolledChance from records) x
where rolledChance < probability;
那我错过了什么? probability
和rolledChance
的使用方式与我在比较中的想法不同吗?每次在同一查询中使用别名时,rand()
是否会被评估?
版本输出:mysql Ver 15.1 Distrib 10.0.28-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2
,在Debian Jessie上运行。
答案 0 :(得分:2)
我认为问题是在GROUP BY之后应用HAVING,但仍然在SELECT阶段之前。我意识到它很混乱,因为HAVING子句引用了SELECT语句中的一个列,但我认为它基本上只执行SELECT语句中的两次 - 一次用于having,然后再用于SELECT。
例如,请参阅https://www.nseindia.com/products/content/equities/equities/homepage_eq.htm。
注意,它特别令人困惑,因为如果你引用一个未出现在HAVING子句的SELECT语句中的列名,它将引发错误。
例如,this answer
但是按照上面的小提琴,它仍然会让你实际根据输出中没有出现的函数的结果进行过滤。简而言之,HAVING子句仍然可以执行您想要的操作,但您不能同时使用该方法过滤随机值并同时显示它。如果需要这样做,则需要使用子查询首先修复该值,然后外部查询可以过滤并显示在其上。
另外,为了清楚起见,可能只需要在having子句中使用RAND(),而不是SQL部分。虽然我知道这个问题是为什么这样做而不是试图专门解决问题。