Definir valor aleatório do conjunto

11

Preciso colocar alguns valores aleatórios no banco de dados, mas não quero terminar com texto completamente aleatório (como 7hfg43d3). Em vez disso, gostaria de escolher aleatoriamente um dos valores fornecidos por mim.

korda
fonte

Respostas:

26

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;

-> SQLfiddle

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)]
Erwin Brandstetter
fonte
teto (0) == piso (0) + 1?
precisa
@korda: Eu adicionei mais, abordando isso.
Erwin Brandstetter
@ErwinBrandstetter, você não acha que ceil(random())::intisso sempre lhe dará 1 para que você não possa verificar se alguma vez retornará 0?
precisa saber é
@ aki92: ceil(0.0)não, esse é o ponto. OTOH: para o objectivo deste teste que pode simplificar: WHERE random() = 0.0.
Erwin Brandstetter
@ErwinBrandstetter oh verdade, desculpe por ter perdido essa coisa.
aki92
8

Tive a ideia de usar Arrays para fazer isso:

(ARRAY['Foo','Bar','Poo'])[floor(random()*3)+1]
korda
fonte
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;

juanra
fonte
Você pode transformar essa função em uma função com parâmetro variável que eu pessoalmente acho mais amigável.
Sahap Asci