Phương pháp truy vấn bản ghi mới nhất trong mỗi nhóm
Phương pháp 1: Sắp xếp + Phân nhóm
Các truy SQL sau có cùng logic cốt lõi:
SELECT *
FROM (SELECT * FROM hoc_sinh ORDER BY thoi_gian_tao DESC) hs
GROUP BY hs.ma_lop;
Hoặc cách viết khác:
SELECT *
FROM hoc_sinh a
JOIN (SELECT id, MAX(thoi_gian_tao) AS thoi_gian_cuoi_cung FROM hoc_sinh GROUP BY ma_lop) b
ON a.id = b.id AND a.thoi_gian_tao = b.thoi_gian_cuoi_cung;
Lưu ý: Trong phiên bản MySQL 5.7 trở đi, nếu truy vấn con chứa ORDER BY kết hợp với GROUP BY, trình tối ưu hóa thường sẽ bỏ qua mệnh đề ORDER BY. Để giải quyết vấn đề này, bạn có thể tham khảo các phương pháp dưới đây.
Phương pháp 2: Sử dụng ID tự tăng và thời gian tạo đồng bộ - Phương pháp khả thi
Phương pháp này hoạt động khi ID tự tăng và thời gian tạo được sắp xếp theo cùng thứ tự:
SELECT *
FROM hoc_sinh
WHERE id IN ( SELECT MAX( id ) FROM hoc_sinh GROUP BY ma_loh)
ORDER BY ma_lop;
Phương pháp 3: Tối ưu hiệu suất khi ID tự tăng và thời gian tạo đồng bộ - Phương pháp khả thi
Phương pháp này tương tự phương pháp 2 nhưng có hiệu suất tốt hơn:
SELECT t1.*
FROM hoc_sinh t1
INNER JOIN ( SELECT MAX( id ) AS id FROM hoc_sinh GROUP BY ma_lop ) t2 ON t1.id = t2.id
Phương pháp 4: Sử dụng DISTINCT để ghi đè tối ưu hóa của MySQL - Phương pháp khả thi
Cách tiếp cận này sử dụng DISTINCT để buộc MySQL thực hiện việc sắp xếp:
SELECT *
FROM ( SELECT DISTINCT * FROM `hoc_sinh` ORDER BY id DESC ) AS t1
GROUP BY t1.ma_loh;
Phương pháp 5: Hàm cửa sổ (Window Function)
Yêu cầu: Phiên bản MySQL 8.0 trở lên.
SELECT * FROM (
SELECT id, ten_hoc_sinh, ma_lop, thoi_gian_tao, ROW_NUMBER() OVER (PARTITION BY ma_lop ORDER BY thoi_gian_tao DESC) AS rowNumber
FROM hoc_sinh
)t
WHERE rowNumber = 1;
Giải thích:
- Truy vấn bảng gốc sử dụng hàm cửa sổ
ROW_NUMBER()để đánh số cho từng bản ghi trong mỗi nhóm. PARTITION BY ma_lopchia dữ liệu theo nhóm mã lớp.ORDER BY thoi_gian_tao DESCsắp xếp giảm dần theo thời gian tạo.- Truy vấn con sau đó được sử dụng để lọc các bản ghi có rowNumber = 1, tức là bản ghi mới nhất trong mỗi nhóm.