Imposta un valore casuale dal set


11

Devo inserire alcuni valori casuali nel database, ma non voglio finire con un testo completamente randomizzato (come 7hfg43d3). Vorrei invece selezionare casualmente uno dei valori forniti da me stesso.

Risposte:


26

Bella idea Suggerisco due semplificazioni minori:

('{Foo,Bar,Poo}'::text[])[ceil(random()*3)]
  • Sintassi più semplice usando un array letterale ( '{Foo,Bar,Poo}'::text[]) Accorcia la stringa per elenchi più lunghi. Vantaggio aggiuntivo: la dichiarazione esplicita del tipo funziona per qualsiasi tipo, non solo per text. L'idea originale viene riprodotta text, perché è il tipo predefinito per i letterali di stringa.

  • Usa ceil()invece di floor() + 1. Stesso risultato

OK, teoricamente, il bordo inferiore potrebbe essere esattamente 0, come suggerito nel tuo commento , poiché random()produce ( citando il manuale qui ):

valore casuale nell'intervallo 0.0 <= x <1.0

Tuttavia, non l'ho mai visto accadere. Esegui un paio di milioni di test:

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

-> SQLfiddle

Per essere perfettamente al sicuro, tuttavia, è possibile utilizzare gli abbonamenti di array personalizzati di Postgres ed evitare comunque l'aggiunta aggiuntiva:

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

Dettagli sotto questa domanda correlata su SO.

O meglio ancora, usa trunc(), è un po 'più veloce.

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

ceil (0) == piano (0) + 1?
Korda,

@korda: ne ho aggiunti altri, affrontandoli.
Erwin Brandstetter,

@ErwinBrandstetter non pensi che ceil(random())::intti darà sempre 1, quindi non sarai in grado di verificare se restituirà mai 0?
aki92,

@ aki92: ceil(0.0)no, questo è il punto. OTOH: Ai fini di questo test potremmo semplificare: WHERE random() = 0.0.
Erwin Brandstetter,

@ErwinBrandstetter oh vero, scusa se ho perso quella cosa.
aki92,

8

Mi è venuta l'idea di usare gli array per realizzare questo:

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

0

Sulla base di questa idea, ho creato una funzione che mi è stata molto utile:

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;

Esempi di utilizzo:

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

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


È possibile trasformare questa funzione in una funzione con parametro variadico che personalmente trovo più user friendly.
Sahap Asci,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.