Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MySQL

สุ่มเลือกแถวข้อมูล (Random Row) ที่มีค่าซ้ำใน MySQL ด้วย RAND() และ LIMIT

ภาพรวม

เมื่อต้องการสุ่มเลือก 1 แถวจากกลุ่มข้อมูลที่มีค่าซ้ำ (Duplicate) ใช้ ORDER BY RAND() ร่วมกับ LIMIT 1 และกรองด้วย WHERE ก่อน

ตัวอย่างสมบูรณ์

1. สร้างตารางและข้อมูล (มีชื่อ 'Bob' ซ้ำ 3 ครั้ง)

CREATE TABLE DemoTable (
    Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    Name VARCHAR(20)
);

INSERT INTO DemoTable (Name) VALUES ('Chris');
INSERT INTO DemoTable (Name) VALUES ('Bob');
INSERT INTO DemoTable (Name) VALUES ('David');
INSERT INTO DemoTable (Name) VALUES ('Bob');
INSERT INTO DemoTable (Name) VALUES ('Bob');

2. ข้อมูลทั้งหมด

SELECT * FROM DemoTable;
+----+-------+
| Id | Name  |
+----+-------+
| 1  | Chris |
| 2  | Bob   |
| 3  | David |
| 4  | Bob   |
| 5  | Bob   |
+----+-------+

3. สุ่มเลือก 1 แถวที่ Name = 'Bob'

SELECT * FROM DemoTable 
WHERE Name = 'Bob' 
ORDER BY RAND() 
LIMIT 1;

4. ผลลัพธ์ (สุ่มทุกครั้ง)

+----+------+
| Id | Name |
+----+------+
| 5  | Bob  |  -- อาจเป็น Id 2, 4, หรือ 5
+----+------+

การทำงานของ RAND()

  • RAND() สร้างเลขสุ่ม 0.0 - 1.0 สำหรับแต่ละแถว
  • ORDER BY RAND() เรียงลำดับแถวตามเลขสุ่ม
  • LIMIT 1 取แถวแรกหลังสุ่ม

ประสิทธิภาพและข้อควรระวัง

⚠️ RAND() ช้าในตารางใหญ่ เพราะต้องคำนวณค่าสุ่มทุกแถว แล้ว Sort ทั้งตาราง

วิธีแก้สำหรับตารางใหญ่ (มากกว่า 10,000 แถว)

วิธี 1: ใช้ ID Range (ถ้า ID เป็น AUTO_INCREMENT ติดต่อกัน)

SELECT * FROM DemoTable
WHERE Name = 'Bob'
  AND Id >= (SELECT FLOOR(RAND() * (SELECT MAX(Id) FROM DemoTable WHERE Name = 'Bob')))
ORDER BY Id LIMIT 1;

วิธี 2: ใช้ OFFSET แบบสุ่ม (ต้องนับจำนวนก่อน)

SET @count = (SELECT COUNT(*) FROM DemoTable WHERE Name = 'Bob');
SET @offset = FLOOR(RAND() * @count);

PREPARE stmt FROM 'SELECT * FROM DemoTable WHERE Name = ? LIMIT ?, 1';
EXECUTE stmt USING 'Bob', @offset;

วิธี 3: สร้างคอลัมน์ Random Seed (Pre-compute)

ALTER TABLE DemoTable ADD COLUMN rand_seed DOUBLE;
UPDATE DemoTable SET rand_seed = RAND();

-- แล้ว Query เร็วมาก
SELECT * FROM DemoTable WHERE Name = 'Bob' ORDER BY rand_seed LIMIT 1;

สรุป

  • ตารางเล็ก (< 1000 แถว): ใช้ ORDER BY RAND() LIMIT 1 ได้เลย
  • ตารางใหญ่: ใช้วิธี Offset หรือ Pre-computed Random Column
  • กรองด้วย WHERE ก่อน ORDER BY RAND() เพื่อลดจำนวนแถวที่ต้องสุ่ม