ฉันต้องใส่ค่าสุ่มลงในฐานข้อมูล แต่ฉันไม่ต้องการที่จะจบลงด้วยข้อความที่สุ่มสมบูรณ์ (เช่น 7hfg43d3) แต่ฉันต้องการสุ่มเลือกค่าหนึ่งค่าที่จัดทำโดยตัวเอง
ฉันต้องใส่ค่าสุ่มลงในฐานข้อมูล แต่ฉันไม่ต้องการที่จะจบลงด้วยข้อความที่สุ่มสมบูรณ์ (เช่น 7hfg43d3) แต่ฉันต้องการสุ่มเลือกค่าหนึ่งค่าที่จัดทำโดยตัวเอง
คำตอบ:
ความคิดดี. ฉันขอแนะนำการทำให้เข้าใจง่ายสองข้อเล็กน้อย:
('{Foo,Bar,Poo}'::text[])[ceil(random()*3)]
ไวยากรณ์ที่ง่ายขึ้นโดยใช้ตัวอักษรอาร์เรย์ ( '{Foo,Bar,Poo}'::text[]
) ทำให้สตริงสั้นลงสำหรับรายการที่ยาวขึ้น ประโยชน์เพิ่มเติม: ประเภทการประกาศอย่างชัดเจนทำงานสำหรับประเภทใด ๆ ไม่เพียง text
แต่สำหรับ แนวคิดดั้งเดิมของคุณเกิดขึ้นกับผลลัพธ์text
เนื่องจากเป็นประเภทเริ่มต้นสำหรับตัวอักษรสตริง
ใช้แทนceil()
floor() + 1
ผลลัพธ์เดียวกัน
ตกลงตามหลักเหตุผลขอบล่างอาจเป็น 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)]
รายละเอียดภายใต้คำถามที่เกี่ยวข้องใน SO
หรือดีกว่ายังใช้งานtrunc()
, ที่บิตเร็วขึ้น
('[0:2]={Foo,Bar,Poo}'::text[])[trunc(random()*3)]
ceil(random())::int
จะให้ 1 คุณเสมอดังนั้นคุณจะไม่สามารถตรวจสอบว่ามันจะกลับมาเป็น 0 หรือไม่?
ceil(0.0)
ไม่หรอกนั่นคือประเด็น OTOH: WHERE random() = 0.0
สำหรับวัตถุประสงค์ของการทดสอบนี้เราอาจจะลดความซับซ้อนของ:
ฉันคิดว่าจะใช้อาร์เรย์เพื่อทำสิ่งนี้:
(ARRAY['Foo','Bar','Poo'])[floor(random()*3)+1]
จากความคิดนี้ฉันได้สร้างฟังก์ชั่นที่ค่อนข้างมีประโยชน์สำหรับฉัน:
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;