web-dev-qa-db-ja.com

セットからランダムな値を設定する

ランダムな値をデータベースに入れる必要がありますが、完全にランダム化されたテキスト(7hfg43d3など)になりたくありません。代わりに、自分で指定した値の1つをランダムに選択します。

11
korda

良い考えです。 2つの小さな簡略化を提案します。

_('{Foo,Bar,Poo}'::text[])[ceil(random()*3)]
_
  • 配列リテラルを使用したより簡単な構文(_'{Foo,Bar,Poo}'::text[]_)長いリストの文字列を短くします。追加の利点:明示的な型宣言は、textだけでなく、あらゆる型で機能します。元のアイデアはtextを出力します。これは文字列リテラルのデフォルトのタイプだからです。

  • ceil()の代わりに floor() + 1 を使用します。同じ結果。

random()は( マニュアルの引用 )を生成するため、理論的には your comment に示唆されているように、下の境界線は正確に0になる可能性があります。

0.0 <= x <1.0の範囲のランダムな値

しかし、私はそれが起こるのを見たことがありません。数百万のテストを実行します。

_SELECT count(*)
FROM   generate_series(1,1000000)
WHERE  ceil(random())::int = 0;
_

-> SQLfiddle

ただし、完全に安全にするために、Postgresカスタム配列添え字を使用しても、追加の追加を回避できます。

_('[0:2]={Foo,Bar,Poo}'::text[])[floor(random()*3)]
_

SOに関するこの関連質問の下の詳細

さらに良い方法として、 trunc() を使用します これは少し高速です。

_('[0:2]={Foo,Bar,Poo}'::text[])[trunc(random()*3)]
_
26

これを実現するために配列を使用するというアイデアが思いつきました。

(ARRAY['Foo','Bar','Poo'])[floor(random()*3)+1]
8
korda

この考えに基づいて、私にとって非常に便利な関数を作成しました。

_CREATE OR REPLACE FUNCTION random_choice(
    choices text[]
)
RETURNS text AS $$
DECLARE
    size_ int;
BEGIN
    size_ = array_length(choices, 1);
    RETURN (choices)[floor(random()*size_)+1];
END
$$ LANGUAGE plpgsql;

_

使用例:

  • SELECT random_choice(array['h', 'i', 'j', 'k', 'l']) as random_char;

  • SELECT random_choice((SELECT array_agg(name) FROM pets)) AS pet_name;

0
juanra