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
- Subquery
d2: Gom nhóm theoValue, gán một số ngẫu nhiênRAND()cho mỗi nhóm. - JOIN: Ghép lại bảng gốc
d1vớid2theoValue. Mỗi hàng trong nhóm nhận cùng mộtrandom_Value. 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 Valuequét toàn bảng. Nên có index trênValue. - 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.