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

สุ่มข้อมูล (Random Rows) ใน MySQL ด้วย ORDER BY RAND() LIMIT


คำสั่งหลัก

ใช้ ORDER BY RAND() LIMIT n สุ่ม n แถว

รูปแบบคำสั่ง

SELECT * FROM yourTableName ORDER BY RAND() LIMIT yourIntegerNumber;

ตัวอย่างครบถ้วน

1. สร้างตารางลูกค้า

mysql> create table gettingRandomRow 
    -> ( 
    -> CustomerId int NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    -> CustomerName varchar(100) 
    -> ); 
Query OK, 0 rows affected (0.45 sec)

2. เพิ่มข้อมูล 13 แถว

mysql> insert into gettingRandomRow(CustomerName) values('Chris'); 
Query OK, 1 row affected (0.14 sec)
mysql> insert into gettingRandomRow(CustomerName) values('Robert'); 
Query OK, 1 row affected (0.10 sec)
mysql> insert into gettingRandomRow(CustomerName) values('Ramit'); 
Query OK, 1 row affected (0.15 sec)
mysql> insert into gettingRandomRow(CustomerName) values('James'); 
Query OK, 1 row affected (0.11 sec)
mysql> insert into gettingRandomRow(CustomerName) values('Jace'); 
Query OK, 1 row affected (0.12 sec)
mysql> insert into gettingRandomRow(CustomerName) values('Mike'); 
Query OK, 1 row affected (0.15 sec)
mysql> insert into gettingRandomRow(CustomerName) values('Sam'); 
Query OK, 1 row affected (0.17 sec)
mysql> insert into gettingRandomRow(CustomerName) values('Bob'); 
Query OK, 1 row affected (0.12 sec)
mysql> insert into gettingRandomRow(CustomerName) values('Carol'); 
Query OK, 1 row affected (0.11 sec)
mysql> insert into gettingRandomRow(CustomerName) values('David'); 
Query OK, 1 row affected (0.16 sec)
mysql> insert into gettingRandomRow(CustomerName) values('Maxwell'); 
Query OK, 1 row affected (0.14 sec)
mysql> insert into gettingRandomRow(CustomerName) values('Larry'); 
Query OK, 1 row affected (0.13 sec)
mysql> insert into gettingRandomRow(CustomerName) values('John'); 
Query OK, 1 row affected (0.11 sec)

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

mysql> select * from gettingRandomRow;
+------------+--------------+
| CustomerId | CustomerName |
+------------+--------------+
| 1          | Chris        |
| 2          | Robert       |
| 3          | Ramit        |
| 4          | James        |
| 5          | Jace         |
| 6          | Mike         |
| 7          | Sam          |
| 8          | Bob          |
| 9          | Carol        |
| 10         | David        |
| 11         | Maxwell      |
| 12         | Larry        |
| 13         | John         |
+------------+--------------+

4. Case 1: สุ่ม 1 แถว

mysql> select * from gettingRandomRow order by rand() LIMIT 1;
+------------+--------------+
| CustomerId | CustomerName |
+------------+--------------+
| 13         | John         |
+------------+--------------+

5. Case 2: สุ่ม 2 แถว (ครั้งที่ 1)

mysql> select * from gettingRandomRow order by rand() LIMIT 2;
+------------+--------------+
| CustomerId | CustomerName |
+------------+--------------+
| 2          | Robert       |
| 3          | Ramit        |
+------------+--------------+

6. Case 3: สุ่ม 2 แถว (ครั้งที่ 2 - ผลต่างออกไป)

mysql> select * from gettingRandomRow order by rand() LIMIT 2;
+------------+--------------+
| CustomerId | CustomerName |
+------------+--------------+
| 4          | James        |
| 9          | Carol        |
+------------+--------------+

Performance Issue: ORDER BY RAND() ช้าบนตารางใหญ่

MySQL ต้อง generate random number ทุกแถว แล้ว sort ทั้งตาราง → O(N log N)

วิธีเร็วกว่าสำหรับตารางใหญ่ (>10K rows)

วิธีที่ 1: Random ID Range (ต้องมี PK แบบ sequential)

SELECT * FROM table 
WHERE id >= (SELECT FLOOR(RAND() * (SELECT MAX(id) FROM table)))
ORDER BY id LIMIT 1;

วิธีที่ 2: 2-Phase (นับก่อน แล้วสุ่ม offset)

-- Phase 1: นับทั้งหมด
SELECT COUNT(*) INTO @total FROM table;

-- Phase 2: สุ่ม offset
SET @offset = FLOOR(RAND() * @total);
PREPARE stmt FROM 'SELECT * FROM table LIMIT ?, 1';
EXECUTE stmt USING @offset;

วิธีที่ 3: TABLESAMPLE (MySQL 8.0.31+)

SELECT * FROM table TABLESAMPLE SYSTEM (10);  -- 10% sample

Seeded Random (Reproducible)

SELECT * FROM table ORDER BY RAND(12345) LIMIT 10;

SEED เดียวกัน = ลำดับสุ่มเดียวกัน (ดีสำหรับ testing)

สรุป: ORDER BY RAND() LIMIT n ใช้ได้ง่าย ตารางเล็ก (<10K) ตารางใหญ่ใช้วิธี alternative