Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> MySQL

Truy xuất nhiều giá trị nhỏ nhất theo nhóm với subquery MIN trong MySQL

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;