从集合中设置随机值


11

我需要将一些随机值放入数据库中,但是我不想最终得到完全随机化的文本(例如7hfg43d3)。相反,我想随机选择我自己提供的值之一。

Answers:


26

好主意。我建议进行两个较小的简化:

('{Foo,Bar,Poo}'::text[])[ceil(random()*3)]
  • 使用数组文字'{Foo,Bar,Poo}'::text[])的语法更简单,可缩短字符串以获取更长的列表。附加好处:显式类型声明适用于任何类型,而不仅适用于text。您最初的想法发生在output上text,因为这是字符串文字的默认类型。

  • 使用ceil()代替floor() + 1。结果相同。

好的,从理论上讲,下边界可以精确地为0,正如您的注释中所暗示的那样,因为random()产生了(在此引用手册):

范围内的随机值0.0 <= x <1.0

但是,我从未见过这种情况。运行几百万个测试:

SELECT count(*)
FROM   generate_series(1,1000000)
WHERE  ceil(random())::int = 0;

-> SQLfiddle的

不过,为了绝对安全,您可以使用Postgres自定义数组下标,并且仍然避免额外的添加:

('[0:2]={Foo,Bar,Poo}'::text[])[floor(random()*3)]

有关SO的这个相关问题的详细信息。

或者更好的使用trunc()这是一个有点快。

('[0:2]={Foo,Bar,Poo}'::text[])[trunc(random()*3)]

天花板(0)==地板(0)+ 1?
korda

@korda:我添加了更多内容,以解决该问题。
Erwin Brandstetter,2013年

@ErwinBrandstetter难道您不认为它ceil(random())::int总是会给您1,所以您将无法检查它是否会返回0?
aki92

@ aki92:ceil(0.0)不会,这就是重点。OTOH:为进行此测试,我们可以简化:WHERE random() = 0.0
Erwin Brandstetter,

@ErwinBrandstetter哦,是的,很抱歉,错过了那件事。
aki92

8

我想出了使用数组来实现此目的的想法:

(ARRAY['Foo','Bar','Poo'])[floor(random()*3)+1]

0

基于这个想法,我创建了一个对我来说非常有用的函数:

CREATE OR REPLACE FUNCTION random_choice(
    choices text[]
)
RETURNS text AS $$
DECLARE
    size_ int;
BEGIN
    size_ = array_length(choices, 1);
    RETURN (choices)[floor(random()*size_)+1];
END
$$ LANGUAGE plpgsql;

用法示例:

  • SELECT random_choice(array['h', 'i', 'j', 'k', 'l']) as random_char;

  • SELECT random_choice((SELECT array_agg(name) FROM pets)) AS pet_name;


您可以将此函数转换为带有可变参数的函数,我个人觉得它更加用户友好。
Sahap Asci
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.