답변:
좋은 생각. 두 가지 사소한 단순화를 제안합니다.
('{Foo,Bar,Poo}'::text[])[ceil(random()*3)]
배열 리터럴 ( '{Foo,Bar,Poo}'::text[]
)을 사용하는 간단한 구문 더 긴 목록을 위해 문자열을 줄입니다. 추가 이점 : 명시 적 형식 선언은을위한 것이 아니라 모든 형식에 사용할 수 있습니다 text
. text
문자열 리터럴의 기본 유형이므로 원래 아이디어가 출력 됩니다.
ceil()
대신에 사용하십시오 floor() + 1
. 같은 결과입니다.
에 암시로 OK, 이론적으로 아래쪽 테두리는 정확히 0이 될 수 귀하의 코멘트 이후 random()
(생산 여기 설명서를 인용 ) :
0.0 <= x <1.0 범위의 난수
그러나 나는 그런 일을 본 적이 없다. 몇 백만 테스트를 실행하십시오.
SELECT count(*)
FROM generate_series(1,1000000)
WHERE ceil(random())::int = 0;
완벽하게 안전하기 위해 Postgres 사용자 정의 배열 첨자를 사용하고 추가 추가를 피할 수 있습니다.
('[0:2]={Foo,Bar,Poo}'::text[])[floor(random()*3)]
또는 더 나은 아직, 사용 trunc()
, 그 조금 더 빠르다.
('[0:2]={Foo,Bar,Poo}'::text[])[trunc(random()*3)]
ceil(random())::int
항상 1을 줄 것이라고 생각하지 않으므로 0을 반환하는지 확인할 수 없습니다.
ceil(0.0)
그렇지 않을 것입니다. OTOH :이 테스트의 목적을 위해 다음을 단순화 할 수 있습니다 WHERE random() = 0.0
..
이 아이디어를 바탕으로 저에게 매우 유용한 기능을 만들었습니다.
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;
사용 예 :
SELECT random_choice(array['h', 'i', 'j', 'k', 'l']) as random_char;
SELECT random_choice((SELECT array_agg(name) FROM pets)) AS pet_name;