19

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

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

任何建议从哪里开始?

4

6 回答 6

44

试试这个:

select (array['Yes', 'No', 'Maybe'])[floor(random() * 3 + 1)];
于 2018-10-23T08:25:35.810 回答
14
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()返回值 x 其中0.0 <= x < 1.0. 乘以三就floor()可以得到01或者机会均等。对于以. 为了提高效率,我改为声明数组索引。210

这些数学函数的手册。

于 2013-01-14T22:44:26.023 回答
7

Erwin Brandstetter很好地回答了 OP 的问题。然而,对于其他想了解如何从更复杂的数组中随机选择元素的人(比如两个月前的我),我扩展了他的功能:

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 的解决方案要慢得多,并且可能会超出您的需求;在实践中,大多数人会从两者中混合一种理想的鸡尾酒

于 2014-07-18T13:30:20.947 回答
5

这是做同样事情的另一种方法

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

您可以将数组更改为您想要的任何类型。

于 2018-06-19T12:03:46.227 回答
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;

对于更大的数据集,请参阅:

于 2020-08-22T15:10:08.490 回答
0
CREATE FUNCTION random_pick(p_items anyarray)
RETURNS anyelement AS
$$
   SELECT unnest(p_items) ORDER BY RANDOM() LIMIT 1;
$$ LANGUAGE SQL;
于 2015-11-25T21:04:59.250 回答