โดยทั่วไปเท่าที่ผมเห็น การจะสั่ง sql ให้ดึงแถวที่ต้องการมาโดยเรียงลำดับแบบสุ่มจะใช้วิธี ORDER BY RAND() เช่น
1 |
SELECT * FROM `table` WHERE 1 ORDER BY RAND() |
แต่วิธีนี้ไม่ใช่วิธีที่ดีเลย เพราะสมมุตว่าข้อมูลมีจะนวน 100000 แถว จะต้องเกิดการ random ค่าทั้งหมด 100000 ครั้ง นอกจากนั้นเมื่อ random เสร็จ ก็ต้องเอาข้อมูลนั้นมาเรียงลำดับใหม่อีกครั้ง ซึ่งในขั้นตอนการเรียง โดยมากแล้ว ตัว Database จะไม่ยอมให้ใช้เนื้อที่เกินจำนวนหนึ่งใน RAM แต่ถ้าข้อมูลเยอะๆแบบนี้ จะใช้การเขียนลง file ก่อน แล้วค่อย sort ซึ่งทำให้ช้ากว่าใน RAM มาก
ดังนั้นผมจึงหาวิธีสุ่มค่าที่มีประสิทธิ์ภาพที่ดีกว่าในเน็ต ซึ่งได้ผลลัพธ์คือเว็บนี้ เค้าแนะนำให้ทำแบบนี้แทนครับ
1 2 3 4 5 6 7 8 9 10 11 12 13 |
SELECT * FROM ( SELECT @cnt := COUNT(*) + 1, @lim := 10 FROM `table` ) vars STRAIGHT_JOIN ( SELECT r.*, @lim := @lim - 1 FROM `table` r WHERE (@cnt := @cnt - 1) AND RAND(20090301) < @lim / @cnt ) i |
โดย table
หมายถึงชื่อตาราง และตรง @lim := 10 หมายถึงต้องการ 10 ตัว ส่วนตัวเลข 20090301 เค้าบอกเป็นเลขอะไรก็ได้ เค้าเอาเลขนี้มาจากวันที่โพส และควรเปลี่ยนทุกครั้ง เพื่อให้ผลไม่เหมือนเดิม
หลักการทำงานคือเหมือนเค้าใช้หลักความน่าจะเป็นแทนการสุ่มมั้งครับ
จริงๆในเว็บต้นฉบับ เค้าบอกมีวิธีสำหรับแถวเดียวอยู่ด้วย แต่ผมไม่สามารถทำความเข้าใจได้ครับ