Giới thiệu
Tìm bản ghi có điểm số thấp nhất (MIN) cho mỗi người (Name) bằng subquery tương quan (correlated subquery).
1. Tạo bảng và dữ liệu
mysql> create table DemoTable (
-> Name varchar(20),
-> Score int
-> );
Query OK, 0 rows affected (0.56 sec)
mysql> insert into DemoTable values('John',56);
Query OK, 1 row affected (0.17 sec)
mysql> insert into DemoTable values('John',45);
Query OK, 1 row affected (0.24 sec)
mysql> insert into DemoTable values('John',58);
Query OK, 1 row affected (0.16 sec)
mysql> insert into DemoTable values('Chris',43);
Query OK, 1 row affected (0.15 sec)
mysql> insert into DemoTable values('Chris',38);
Query OK, 1 row affected (0.14 sec)
mysql> insert into DemoTable values('Chris',87);
Query OK, 1 row affected (0.14 sec)
2. Dữ liệu gốc
mysql> select *from DemoTable;
+-------+-------+ | Name | Score | +-------+-------+ | John | 56 | | John | 45 | | John | 58 | | Chris | 43 | | Chris | 38 | | Chris | 87 | +-------+-------+ 6 rows in set (0.00 sec)
3. Truy vấn tìm điểm thấp nhất mỗi người
mysql> select *from DemoTable tbl1
-> where Score IN (
-> select min(Score) from DemoTable tbl2
-> where tbl1.Name = tbl2.Name
-> );
4. Kết quả
+-------+-------+ | Name | Score | +-------+-------+ | John | 45 | | Chris | 38 | +-------+-------+ 2 rows in set (0.00 sec)
Giải thích: Subquery chạy cho mỗi hàng của tbl1, tìm MIN(Score) của cùng Name. Nếu Score của hàng hiện tại = MIN đó → giữ lại.
Cách hiện đại hơn (MySQL 8.0+ - Window Function):
SELECT Name, Score
FROM (
SELECT Name, Score,
ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Score ASC) as rn
FROM DemoTable
) t
WHERE rn = 1;
Cách JOIN (hiệu quả trên MySQL cũ):
SELECT t1.Name, t1.Score
FROM DemoTable t1
JOIN (
SELECT Name, MIN(Score) as min_score
FROM DemoTable
GROUP BY Name
) t2 ON t1.Name = t2.Name AND t1.Score = t2.min_score;