PostgreSQL PL/pgSQL值的数组随机值

Mo *_*abi 4 arrays random postgresql plpgsql postgresql-9.2

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

a := [1, 2, 5] -- sample sake
select random(a) -- returns random value
Run Code Online (Sandbox Code Playgroud)

有什么建议从哪里开始?

Erw*_*ter 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
Run Code Online (Sandbox Code Playgroud)

random()返回值x where 0.0 <= x < 1.0.乘以三,floor()它得到0,12相同的机会.对于以...开头的默认数组索引,这将是一个接一个1.为了提高效率,我将数组索引声明为开头0.

关于这些数学函数的手册.


Yak*_*ein 9

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

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

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


Pav*_* V. 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;
Run Code Online (Sandbox Code Playgroud)

几个假设:

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

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

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

  • 这是用于一维数组

其他注意事项:

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

  • 如果没有循环,间隙和 NULL 将使函数返回 NULL

  • array_lower如果您知道数组从零开始,则省略这两个调用

  • 索引中存在间隙,您将需要array_upper而不是array_length; 没有间隙,它是一样的(不确定哪个更快,但它们应该没有太大区别)

  • 所述+1后第二array_lower用于获得具有相同概率的任何其他阵列中的最后一个值; 否则它将需要random()的输出恰好为 1,这永远不会发生

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


And*_*rul 5

试试这个:

select (array['Yes', 'No', 'Maybe'])[floor(random() * 3 + 1)];
Run Code Online (Sandbox Code Playgroud)

  • 对我来说这是最好的答案,因为不需要任何功能 (4认同)
  • 如果数组中的项目超过 3 个,这会起到同样的作用吗?另外你想知道如何获得 2 个随机物品而不是 1 个吗?谢谢! (2认同)
  • 最好澄清一下神奇数字代表什么。如果我想在具有不同数量项目的数组上尝试此操作,我会使用什么幻数?我想这里的“3”代表数组的长度,那么无论数组长度如何,我们都应该始终“+ 1”? (2认同)