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

MySQL: เลือกแถวเฉพาะเจาะจง 1 แถว และอีกแถวสุ่ม (RAND)

การเลือก 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) วิธีแก้:

  1. สุ่มใน Application Layer (ดึง ID มาสุ่ม แล้ว Query BY ID)
  2. ใช้ WHERE Id >= (SELECT FLOOR(RAND() * (SELECT MAX(Id) FROM t))) (ประมาณการ)
  3. เพิ่ม Column Random_Sort INT, Update ด้วย RAND() ทุกครั้ง, Index บนมัน