2013-01-12 30 views

回答

8
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()它得到0,12相等的機會。對於以1開頭的默認數組索引,這將是錯誤的。爲了提高效率,我聲明數組索引以0開頭。

The manual on these mathematical functions.

+0

一個理想的雞尾酒非常感謝你,這是有益的 –

2

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的解決方案要慢很多,並且可能會成爲您需要的矯枉過正;在實踐中,大多數人會混合來自兩個

0
CREATE FUNCTION random_pick(p_items anyarray) 
RETURNS anyelement AS 
$$ 
    SELECT unnest(p_items) ORDER BY RANDOM() LIMIT 1; 
$$ LANGUAGE SQL; 
+0

這似乎不再是PostgreSQL中9.6的工作:https://stackoverflow.com/questions/42179012 /如何對洗牌陣列合的PostgreSQL-9-6和 - 還 - 低級 - 版本 –