Vấn đề: Loại bỏ hàng đầu tiên và cuối cùng theo nhóm
Cần truy vấn các hàng "giữa" – bỏ qua hàng có ID nhỏ nhất và lớn nhất trong mỗi nhóm (ví dụ: theo StudentCode).
Giải pháp: Subquery với MIN() và MAX()
Dùng NOT IN kết hợp subquery lấy MIN(StudentId) và MAX(StudentId) cho từng nhóm.
1. Tạo bảng và dữ liệu
CREATE TABLE DemoTable (
StudentId INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
StudentCode INT,
StudentMarks INT
);
INSERT INTO DemoTable (StudentCode, StudentMarks) VALUES
(78, 95), (78, 96), (78, 97), (78, 98), (78, 99);
2. Dữ liệu đầy đủ
+-----------+-------------+--------------+
| StudentId | StudentCode | StudentMarks |
+-----------+-------------+--------------+
| 1 | 78 | 95 |
| 2 | 78 | 96 |
| 3 | 78 | 97 |
| 4 | 78 | 98 |
| 5 | 78 | 99 |
+-----------+-------------+--------------+
3. Truy vấn lấy hàng giữa
SELECT * FROM DemoTable
WHERE StudentId NOT IN (
(SELECT MIN(StudentId) FROM DemoTable WHERE StudentCode = 78),
(SELECT MAX(StudentId) FROM DemoTable WHERE StudentCode = 78)
) AND StudentCode = 78;
4. Kết quả (bỏ ID 1 và 5)
+-----------+-------------+--------------+
| StudentId | StudentCode | StudentMarks |
+-----------+-------------+--------------+
| 2 | 78 | 96 |
| 3 | 78 | 97 |
| 4 | 78 | 98 |
+-----------+-------------+--------------+
Cách hiện đại hơn (MySQL 8.0+): Window Functions
WITH Ranked AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY StudentCode ORDER BY StudentId) AS rn_asc,
ROW_NUMBER() OVER (PARTITION BY StudentCode ORDER BY StudentId DESC) AS rn_desc
FROM DemoTable
)
SELECT StudentId, StudentCode, StudentMarks
FROM Ranked
WHERE rn_asc > 1 AND rn_desc > 1;
Ưu điểm: Hiệu suất tốt hơn trên dữ liệu lớn, dễ mở rộng cho nhiều nhóm.
Lưu ý
- Đảm bảo cột sắp xếp (
StudentId) xác định thứ tự rõ ràng. - Nếu nhóm chỉ có 1 hoặc 2 hàng, kết quả sẽ rỗng – hợp lý.
- Subquery
NOT INcó thể chậm trên bảng lớn; ưu tiênNOT EXISTShoặc Window Functions.