การเลือก 1 แถวเฉพาะเจาะจง + แถวสุ่ม ด้วย ORDER BY (Condition) DESC, RAND()
เทคนิคนี้ใช้ ORDER BY (Id = target_id) DESC เพื่อบังคับให้แถว Target อยู่บนสุด (TRUE=1 มากกว่า FALSE=0) แล้วตามด้วย RAND() สำหรับแถวที่เหลือ
ตัวอย่างการใช้งาน
สร้างตารางและเพิ่มข้อมูล 7 แถว:
mysql> CREATE TABLE oneSpecificRowAndOtherRandom (
-> Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> Name VARCHAR(20)
-> );
Query OK, 0 rows affected (0.72 sec)
mysql> INSERT INTO oneSpecificRowAndOtherRandom(Name) VALUES('Larry'),('Sam'),('Mike'),('Carol'),('Chris'),('Bob'),('David');
Query OK, 7 rows affected (0.15 sec)
ข้อมูลทั้งหมด:
mysql> SELECT * FROM oneSpecificRowAndOtherRandom;
+----+-------+
| Id | Name |
+----+-------+
| 1 | Larry |
| 2 | Sam |
| 3 | Mike |
| 4 | Carol |
| 5 | Chris |
| 6 | Bob |
| 7 | David |
+----+-------+
7 rows in set (0.00 sec)
เลือก Id=5 (Chris) บังคับบนสุด + สุ่มอีก 2 แถว (LIMIT 3):
mysql> SELECT * FROM oneSpecificRowAndOtherRandom
-> ORDER BY (Id = 5) DESC, RAND()
-> LIMIT 0, 3;
+----+-------+
| Id | Name |
+----+-------+
| 5 | Chris |
| 1 | Larry |
| 2 | Sam |
+----+-------+
3 rows in set (0.05 sec)
รันอีกครั้ง (RAND() ให้แถวสุ่มต่างกัน):
mysql> SELECT * FROM oneSpecificRowAndOtherRandom
-> ORDER BY (Id = 5) DESC, RAND()
-> LIMIT 0, 3;
+----+-------+
| Id | Name |
+----+-------+
| 5 | Chris |
| 2 | Sam |
| 4 | Carol |
+----+-------+
3 rows in set (0.00 sec)
คำอธิบาย
(Id = 5)คืนค่า 1 (TRUE) สำหรับแถว Id=5, 0 (FALSE) สำหรับอื่นDESCเรียง 1 ก่อน 0 → แถว Target อยู่บนสุดเสมอRAND()เรียงสุ่มแถวที่เหลือ (False group)LIMIT 0, 3= ข้าม 0 แถว, ดึง 3 แถว (Target + 2 Random)
ประยุกต์ใช้: หลาย Target (IN)
ORDER BY (Id IN (3,5,7)) DESC, RAND() LIMIT 5;
-- แถว 3,5,7 อยู่บนสุด (เรียงตาม Id ในกลุ่ม TRUE) แล้วสุ่มอื่นๆ
ข้อควรระวังประสิทธิภาพ
ORDER BY RAND() ทำ Full Table Scan + Filesort ช้ามากตารางใหญ่ (>10K rows) วิธีแก้:
- สุ่มใน Application Layer (ดึง ID มาสุ่ม แล้ว Query BY ID)
- ใช้
WHERE Id >= (SELECT FLOOR(RAND() * (SELECT MAX(Id) FROM t)))(ประมาณการ) - เพิ่ม Column Random_Sort INT, Update ด้วย RAND() ทุกครั้ง, Index บนมัน