Muszę umieścić jakieś losowe wartości w bazie danych, ale nie chcę kończyć całkowicie losowym tekstem (np. 7hfg43d3). Zamiast tego chciałbym losowo wybrać jedną z wartości dostarczonych przez siebie.
źródło
Muszę umieścić jakieś losowe wartości w bazie danych, ale nie chcę kończyć całkowicie losowym tekstem (np. 7hfg43d3). Zamiast tego chciałbym losowo wybrać jedną z wartości dostarczonych przez siebie.
Dobry pomysł. Proponuję dwa niewielkie uproszczenia:
('{Foo,Bar,Poo}'::text[])[ceil(random()*3)]
Prostsza składnia za pomocą literału tablicowego ( '{Foo,Bar,Poo}'::text[]
) Skraca ciąg dla dłuższych list. Dodatkowa korzyść: wyraźna deklaracja typu działa dla każdego typu, nie tylko dla text
. Twój oryginalny pomysł jest generowany text
, ponieważ jest to domyślny typ literałów łańcuchowych.
Użyj ceil()
zamiast floor() + 1
. Ten sam wynik.
OK, teoretycznie, dolna granica może wynosić dokładnie 0, jak wskazano w komentarzu , ponieważ random()
tworzy ( cytując tutaj instrukcję ):
wartość losowa w zakresie 0,0 <= x <1,0
Jednak nigdy tego nie widziałem. Przeprowadź kilka milionów testów:
SELECT count(*)
FROM generate_series(1,1000000)
WHERE ceil(random())::int = 0;
Aby być całkowicie bezpiecznym, możesz użyć niestandardowych indeksów tablic Postgres i nadal unikać dodatkowego dodawania:
('[0:2]={Foo,Bar,Poo}'::text[])[floor(random()*3)]
Szczegóły dotyczące tego powiązanego pytania dotyczącego SO.
Lub jeszcze lepiej, użyj trunc()
, to trochę szybciej.
('[0:2]={Foo,Bar,Poo}'::text[])[trunc(random()*3)]
ceil(random())::int
zawsze da ci 1, więc nie będziesz w stanie sprawdzić, czy kiedykolwiek zwróci 0?ceil(0.0)
nie, właśnie o to chodzi. OTOH: dla celów tego badania możemy uprościć:WHERE random() = 0.0
.Wpadłem na pomysł użycia tablic, aby to osiągnąć:
źródło
W oparciu o ten pomysł stworzyłem funkcję, która była dla mnie bardzo przydatna:
Przykłady użycia:
SELECT random_choice(array['h', 'i', 'j', 'k', 'l']) as random_char;
SELECT random_choice((SELECT array_agg(name) FROM pets)) AS pet_name;
źródło