使用`rand()`和`having`

时间:2017-06-12 09:32:21

标签: mysql mariadb

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

但是,某些不起作用,导致返回的行不符合使用别名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;

那我错过了什么? probabilityrolledChance的使用方式与我在比较中的想法不同吗?每次在同一查询中使用别名时,rand()是否会被评估?

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

1 个答案:

答案 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部分。虽然我知道这个问题是为什么这样做而不是试图专门解决问题。