Stellen Sie einen zufälligen Wert aus dem Satz ein


11

Ich muss einige zufällige Werte in die Datenbank einfügen, möchte aber keinen vollständig zufälligen Text erhalten (wie 7hfg43d3). Stattdessen möchte ich zufällig einen von mir gelieferten Wert auswählen.

Antworten:


26

Gute Idee. Ich schlage zwei kleinere Vereinfachungen vor:

('{Foo,Bar,Poo}'::text[])[ceil(random()*3)]
  • Einfachere Syntax mit einem Array-Literal ( '{Foo,Bar,Poo}'::text[]) Verkürzt die Zeichenfolge für längere Listen. Zusätzlicher Vorteil: Die explizite Typdeklaration funktioniert für jeden Typ, nicht nur für text. Ihre ursprüngliche Idee wird zufällig ausgegeben text, da dies der Standardtyp für Zeichenfolgenliterale ist.

  • Verwenden Sie ceil()anstelle von floor() + 1. Gleiches Ergebnis.

OK, theoretisch könnte der untere Rand genau 0 sein, wie in Ihrem Kommentar angedeutet , da random()erzeugt ( zitiert das Handbuch hier ):

Zufallswert im Bereich 0.0 <= x <1.0

Ich habe das jedoch noch nie gesehen. Führen Sie einige Millionen Tests durch:

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

-> SQLfiddle

Um jedoch absolut sicher zu sein, können Sie benutzerdefinierte Array-Indizes von Postgres verwenden und dennoch die zusätzliche Hinzufügung vermeiden:

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

Details unter dieser verwandten Frage zu SO.

Oder noch besser, verwenden Sie trunc(), das ist ein bisschen schneller.

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

Decke (0) == Boden (0) + 1?
Korda

@korda: Ich habe mehr hinzugefügt, um das anzusprechen.
Erwin Brandstetter

@ErwinBrandstetter Glaubst du nicht, dass ceil(random())::intdu immer 1 bekommst, damit du nicht überprüfen kannst, ob es jemals 0 zurückgibt ?
Aki92

@ aki92: ceil(0.0)würde nicht, das ist der Punkt. OTOH: Für den Zweck dieses Tests könnten wir vereinfachen : WHERE random() = 0.0.
Erwin Brandstetter

@ErwinBrandstetter oh wahr, sorry, habe das Ding einfach verpasst.
Aki92

8

Ich hatte die Idee, Arrays zu verwenden, um dies zu erreichen:

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

0

Basierend auf dieser Idee habe ich eine Funktion erstellt, die für mich sehr nützlich war:

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;

Anwendungsbeispiele:

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

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


Sie können diese Funktion in eine Funktion mit variablen Parametern verwandeln , die ich persönlich benutzerfreundlicher finde.
Sahap Asci
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.