为什么在case语句中调用random()会产生意外结果?

时间:2014-12-06 02:02:29

标签: postgresql random case

https://gist.github.com/anonymous/2463d5a8ee2849a6e1f5

查询1不会产生预期结果。但是,查询2和3可以。为什么将调用移到case语句之外的random()很重要?

1 个答案:

答案 0 :(得分:1)

考虑第一个表达式:

select (case when round(random()*999999) + 1 between 000001 and 400000 then 1
             when round(random()*999999) + 1 between 400001 and 999998 then 2
             when round(random()*999999) + 1 between 999999 and 999999 then 3
             else 4
        end)
from generate_series(1, 8000000)

据推测,您认为几乎不应该选择值“4”。但是,问题是random()是为每个when子句单独调用的。

因此,每个条款失败的可能性是独立的:

  • 大约60%的时间随机数与“1”不匹配。
  • 大约40%的时间随机数与“2”不匹配。
  • 随机数约为99.9999%的时间与“3”不匹配(如果9号的数量已关闭,我道歉,但实际值为1)。

这意味着大约24%的时间(60%* 40%* 99.9999%),将出现值“4”。实际上,第一个查询在23.98%的时间内返回“4”。说实话,这非常接近实际值,但考虑到这个数据大小,但它比我预期的要稍微偏远。但是,它足以说明正在发生的事情。