Khi dùng GROUP BY, MySQL (trước 5.7 ONLY_FULL_GROUP_BY) cho phép chọn cột không gom nhóm, nhưng kết quả không xác định. Để chọn hàng cụ thể (ví dụ: ID nhỏ nhất) cho mỗi nhóm, dùng subquery với MIN() hoặc MAX().
Ví dụ minh họa
Tạo bảng điểm học sinh (có 2 học sinh 79 điểm):
CREATE TABLE DemoTable1572 (
StudentId INT, StudentMarks INT, StudentName VARCHAR(20)
);
INSERT INTO DemoTable1572 VALUES
(1, 79, 'Sam'), (2, 89, 'Chris'), (3, 98, 'David'), (4, 79, 'Bob');
Lấy 1 hàng cho mỗi mức điểm (hàng có StudentId nhỏ nhất):
SELECT * FROM DemoTable1572
WHERE StudentId IN (
SELECT MIN(StudentId) FROM DemoTable1572 GROUP BY StudentMarks
);
Kết quả
| StudentId | StudentMarks | StudentName |
|---|---|---|
| 1 | 79 | Sam |
| 2 | 89 | Chris |
| 3 | 98 | David |
→ Nhóm 79 điểm: chọn Id=1 (Sam) thay vì Id=4 (Bob).
MySQL 8.0+: Window Function (chuẩn, mạnh hơn)
SELECT StudentId, StudentMarks, StudentName
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY StudentMarks ORDER BY StudentId) AS rn
FROM DemoTable1572
) t
WHERE rn = 1;
PARTITION BY StudentMarks: Chia nhóm theo điểm.ORDER BY StudentId: Sắp xếp trong nhóm.ROW_NUMBER(): Đánh số 1,2,3... trong nhóm.WHERE rn = 1: Lấy hàng đầu tiên mỗi nhóm.
So sánh
| Cách | Ưu điểm | Nhược điểm |
|---|---|---|
| Subquery MIN/MAX | Tương thích mọi phiên bản | Chỉ lấy được cột dùng trong aggregate |
| JOIN derived table | Lấy được toàn bộ cột | Verbose |
| Window Function | Linh hoạt (top N, tie-break phức tạp) | Chỉ MySQL 8.0+ |