CREATE OR REPLACE FUNCTION random_pick()
RETURNS int
LANGUAGE sql VOLATILE PARALLEL SAFE AS
$func$
SELECT ('[0:2]={1,2,5}'::int[])[trunc(random() * 3)::int];
$func$;
random()返回值x,其中0.0 <= x < 1.0。乘以3,然后用trunc()将其截断(比floor()稍快),以获得0、1或2,且 * 几率完全相等 *。 Postgres索引默认从1开始(根据SQL标准)。这将是一个差1。我们可以每次递增1,但为了提高效率,我声明数组索引从0开始。但稍微快一点。请参见:
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;
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;
6条答案
按热度按时间mf98qq941#
试试这个:
8ftvxx2r2#
更新于2023-01-10,修复了损坏的数组文字。使其在使用时速度提高了几倍:
random()
返回值x
,其中0.0 <= x < 1.0
。乘以3
,然后用trunc()
将其截断(比floor()
稍快),以获得0
、1
或2
,且 * 几率完全相等 *。Postgres索引默认从1开始(根据SQL标准)。这将是一个差1。我们可以每次递增1,但为了提高效率,我声明数组索引从
0
开始。但稍微快一点。请参见:PARALLEL SAFE
适用于Postgres 9.6或更高版本。请参见:如果不想创建函数,可以使用普通的
SELECT
语句:3gtaxfhh3#
然而,对于其他想了解如何从更复杂的数组中随机选取元素的人(就像两个月前的我),我扩展了他的函数:
几个假设:
其他注意事项:
IF
语句,空数组将导致无限循环array_lower
调用array_upper
而不是array_length
;没有间隙,它们是相同的(不确定哪个更快,但它们应该没有太大区别)array_lower
之后的+1
用于以与任何其他值相同的概率获得数组中的最后一个值;否则,它将需要random()
的输出恰好为1,而这永远不会发生fnx2tebb4#
下面是执行相同操作的另一种方法
您可以将数组更改为所需的任何类型。
jtw3ybtb5#
或
对于更大的数据集,请参见:
fbcarpbf6#