Respostas:
Boa ideia. Sugiro duas pequenas simplificações:
('{Foo,Bar,Poo}'::text[])[ceil(random()*3)]
Sintaxe mais simples usando um array literal ( '{Foo,Bar,Poo}'::text[]
) Reduz a string para listas mais longas. Benefício adicional: declaração explícita de tipo funciona para qualquer tipo, não apenas para text
. Sua ideia original é exibida text
, porque esse é o tipo padrão para literais de strings.
Use em ceil()
vez de floor() + 1
. Mesmo resultado.
OK, teoricamente, a borda inferior pode ser 0 com precisão, conforme sugerido no seu comentário , já que random()
produz ( citando o manual aqui ):
valor aleatório no intervalo 0,0 <= x <1,0
No entanto, nunca vi isso acontecer. Execute alguns milhões de testes:
SELECT count(*)
FROM generate_series(1,1000000)
WHERE ceil(random())::int = 0;
Para ser perfeitamente seguro, você pode usar os subscritos de matriz personalizados do Postgres e ainda evitar a adição extra:
('[0:2]={Foo,Bar,Poo}'::text[])[floor(random()*3)]
Detalhes nesta pergunta relacionada ao SO.
Ou melhor ainda, o uso trunc()
, que é um pouco mais rápido.
('[0:2]={Foo,Bar,Poo}'::text[])[trunc(random()*3)]
ceil(random())::int
isso sempre lhe dará 1 para que você não possa verificar se alguma vez retornará 0?
ceil(0.0)
não, esse é o ponto. OTOH: para o objectivo deste teste que pode simplificar: WHERE random() = 0.0
.
Com base nessa idéia, criei uma função que foi bastante útil para mim:
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;
Exemplos de uso:
SELECT random_choice(array['h', 'i', 'j', 'k', 'l']) as random_char;
SELECT random_choice((SELECT array_agg(name) FROM pets)) AS pet_name;