Đặt giá trị ngẫu nhiên từ bộ


11

Tôi cần đặt một số giá trị ngẫu nhiên vào cơ sở dữ liệu, nhưng tôi không muốn kết thúc bằng văn bản hoàn toàn ngẫu nhiên (như 7hfg43d3). Thay vào đó, tôi muốn chọn ngẫu nhiên một trong những giá trị do mình cung cấp.

Câu trả lời:


26

Ý kiến ​​hay. Tôi đề nghị hai đơn giản hóa nhỏ:

('{Foo,Bar,Poo}'::text[])[ceil(random()*3)]
  • Cú pháp đơn giản hơn bằng cách sử dụng một mảng bằng chữ ( '{Foo,Bar,Poo}'::text[]) Rút ngắn chuỗi cho danh sách dài hơn. Lợi ích bổ sung: khai báo kiểu rõ ràng hoạt động cho bất kỳ loại nào, không chỉ cho text. Ý tưởng ban đầu của bạn xảy ra với đầu ra text, bởi vì đó là loại mặc định cho chuỗi ký tự.

  • Sử dụng ceil()thay vì floor() + 1. Cùng một kết quả.

OK, về mặt lý thuyết, đường viền dưới có thể là 0 chính xác, như được gợi ý trong nhận xét của bạn , kể từ khi random()sản xuất ( trích dẫn hướng dẫn ở đây ):

giá trị ngẫu nhiên trong phạm vi 0,0 <= x <1,0

Tuy nhiên, tôi chưa bao giờ thấy điều đó xảy ra. Chạy một vài triệu bài kiểm tra:

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

-> SQLfiddle

Tuy nhiên, để hoàn toàn an toàn, bạn có thể sử dụng các đăng ký mảng tùy chỉnh của Postgres và vẫn tránh bổ sung thêm:

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

Chi tiết theo câu hỏi liên quan này trên SO.

Hoặc tốt hơn, sử dụng trunc(), đó là một chút nhanh hơn.

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

trần (0) == sàn (0) + 1?
korda

@korda: Tôi đã thêm nhiều hơn, giải quyết điều đó.
Erwin Brandstetter

@ErwinBrandstetter bạn không nghĩ rằng ceil(random())::intsẽ luôn cung cấp cho bạn 1 vì vậy bạn sẽ không thể kiểm tra xem nó có trở về 0 không?
aki92

@ aki92: ceil(0.0)sẽ không, đó là điểm chính. OTOH: cho mục đích thử nghiệm này, chúng tôi có thể đơn giản hóa : WHERE random() = 0.0.
Erwin Brandstetter

@ErwinBrandstetter ồ, xin lỗi chỉ cần bỏ lỡ điều đó.
aki92

8

Tôi đã nảy ra ý tưởng sử dụng Mảng để thực hiện điều này:

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

0

Dựa trên ý tưởng này, tôi đã tạo ra một chức năng khá hữu ích cho tôi:

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;

Ví dụ sử dụng:

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

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


Bạn có thể biến chức năng này thành một chức năng với tham số matrixdic mà cá nhân tôi thấy thân thiện với người dùng hơn.
Sahap Asci
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.