PostgreSQL PL / pgSQL值的数组随机值

时间:2013-01-12 23:27:30

标签: arrays postgresql random plpgsql postgresql-9.2

如何使用两个或三个值声明一个类似变量的数组,并在执行期间随机获取它们?

a := [1, 2, 5] -- sample sake
select random(a) -- returns random value

有什么建议从哪里开始?

6 个答案:

答案 0 :(得分:11)

CREATE FUNCTION random_pick()
  RETURNS int AS
$func$
DECLARE
   a int[] := '{[0:2]=1,2,5}'; -- sample sake
BEGIN
   RETURN a[floor((random()*3))::int];
END
$func$ LANGUAGE plpgsql VOLATILE

random()返回值0.0 <= x < 1.0。乘以3和floor()得到012 等于偶数。对于以1开头的默认数组索引,这将是一个一个。为了提高效率,我声明数组索引改为以0开头。

The manual on these mathematical functions.

答案 1 :(得分:4)

Erwin Brandstetter answered the OP's question已经足够了。然而,对于其他寻求理解如何从更复杂的数组中随机选择元素的人(比如两个月前的我),我扩展了他的功能:

CREATE OR REPLACE FUNCTION random_pick( a anyarray, OUT x anyelement )
  RETURNS anyelement AS
$func$
BEGIN
  IF a = '{}' THEN
    x := NULL::TEXT;
  ELSE
    WHILE x IS NULL LOOP
      x := a[floor(array_lower(a, 1) + (random()*( array_upper(a, 1) -  array_lower(a, 1)+1) ) )::int];
    END LOOP;
  END IF;
END
$func$ LANGUAGE plpgsql VOLATILE RETURNS NULL ON NULL INPUT;

几个假设:

  • 这不仅适用于整数数组,也适用于任何类型的数组

  • 我们忽略NULL数据;仅当数组为空或插入NULL时才返回NULL(其他非数组类型的值产生错误)

  • 数组不需要像往常一样进行格式化 - 数组索引可以在任何地方开始和结束,也可能有间隙等。

  • 这适用于一维数组

其他说明:

  • 没有第一个IF语句,空数组将导致无限循环

  • 没有循环,间隙和NULL会使函数返回NULL

  • 如果您知道阵列从零开始,则省略array_lower次调用

  • 如果索引中存在空白,则需要array_upper而不是array_length;没有差距,它是一样的(不确定哪个更快,但它们不应该有太大不同)

  • 第二个+1之后的array_lower用于获取数组中的最后一个值,其概率与其他任何值相同;否则它需要random()的输出正好为1,这绝不会发生

  • 这比Erwin的解决方案慢得多,而且可能对你的需求来说太过分了;在实践中,大多数人会混合两种理想的鸡尾酒

答案 2 :(得分:2)

尝试这个:

select (array['Yes', 'No', 'Maybe'])[floor(random() * 3 + 1)];

答案 3 :(得分:2)

CREATE OR REPLACE FUNCTION pick_random( members anyarray )
RETURNS anyelement AS
$$
BEGIN
  RETURN members[trunc(random() * array_length(members, 1) + 1)];
END
$$ LANGUAGE plpgsql VOLATILE;

CREATE OR REPLACE FUNCTION pick_random( members anyarray )
RETURNS anyelement AS
$$
  SELECT (array_agg(m1 order by random()))[1]
  FROM unnest(members) m1;
$$ LANGUAGE SQL VOLATILE;

有关更大的数据集,请参阅:

答案 4 :(得分:1)

这是做同一件事的另一种方式

WITH arr AS (
    SELECT '{1, 2, 5}'::INT[] a
)
SELECT a[1 + floor((random() * array_length(a, 1)))::int] FROM arr;

您可以将数组更改为所需的任何类型。

答案 5 :(得分:0)

<div class="form-group">
    <input type="text" id="address" name="address" required value="{{input.address}}">
</div>
<div class="form-group">
    <input type="text" id="companyName" name="companyName" required value="{{input.companyName}}">
</div>
<div class="form-group">
    <input type="text" id="manager" name="staff[manager]" required value="{{input.staff.manager}}">
</div>
<div class="form-group">
    <input type="text" id="receptionist" name="staff[receptionist]" required value="{{input.staff.receptionist}}">
</div>