Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> MySQL

Sắp xếp nhóm (GROUP) ngẫu nhiên trong MySQL (Random Order per Group)

Yêu cầu: Gom nhóm các hàng theo một cột (ví dụ: Value), nhưng thứ tự các nhóm hiển thị ngẫu nhiên, trong khi thứ tự bên trong nhóm giữ nguyên (hoặc cũng ngẫu nhiên). Kỹ thuật: Tạo bảng dẫn xuất (derived table) chọn một giá trị ngẫu nhiên cho mỗi nhóm, sau đó JOIN ngược lại bảng gốc.

Tạo bảng và dữ liệu

mysql> CREATE TABLE DemoTable (
    Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    Value CHAR(1)
);

mysql> INSERT INTO DemoTable (Value) VALUES
('X'), ('Y'), ('X'), ('X'), ('Y'), ('Z'), ('Z');

Dữ liệu (3 nhóm: X, Y, Z)

mysql> SELECT * FROM DemoTable;
+----+-------+
| Id | Value |
+----+-------+
|  1 | X     |
|  2 | Y     |
|  3 | X     |
|  4 | X     |
|  5 | Y     |
|  6 | Z     |
|  7 | Z     |
+----+-------+

Truy vấn: Nhóm theo Value, thứ tự nhóm ngẫu nhiên

mysql> SELECT d1.* 
FROM DemoTable d1
JOIN (
    SELECT Value, RAND() AS random_Value
    FROM DemoTable
    GROUP BY Value
) d2 ON d1.Value = d2.Value
ORDER BY d2.random_Value;

Kết quả lần 1 (Nhóm Z trước, rồi X, rồi Y)

+----+-------+
| Id | Value |
+----+-------+
|  6 | Z     |
|  7 | Z     |
|  1 | X     |
|  3 | X     |
|  4 | X     |
|  2 | Y     |
|  5 | Y     |
+----+-------+

Kết quả lần 2 (Chạy lại, thứ tự nhóm thay đổi: Y, Z, X)

+----+-------+
| Id | Value |
+----+-------+
|  2 | Y     |
|  5 | Y     |
|  6 | Z     |
|  7 | Z     |
|  1 | X     |
|  3 | X     |
|  4 | X     |
+----+-------+

Giải thích

  1. Subquery d2: Gom nhóm theo Value, gán một số ngẫu nhiên RAND() cho mỗi nhóm.
  2. JOIN: Ghép lại bảng gốc d1 với d2 theo Value. Mỗi hàng trong nhóm nhận cùng một random_Value.
  3. ORDER BY d2.random_Value: Sắp xếp toàn bộ kết quả theo số ngẫu nhiên của nhóm -> các nhóm xen kẽ ngẫu nhiên, bên trong nhóm giữ thứ tự gốc (theo Id do PK).

Biến thể: Ngẫu nhiên cả bên trong nhóm

ORDER BY d2.random_Value, RAND()

Lưu ý hiệu năng

  • Subquery GROUP BY Value quét toàn bảng. Nên có index trên Value.
  • Với bảng rất lớn, cân nhắc lấy mẫu (sampling) hoặc xử lý ở tầng ứng dụng.