Trong các cơ sở dữ liệu, việc xếp hạng các mục theo một tiêu chí cụ thể là một nhiệm vụ phổ biến. Trong MySQL, mặc dù không có sẵn hàm RANK() như trong một số hệ quản trị cơ sở dữ liệu khác, ta vẫn có thể sử dụng các phương pháp khác để tính toán thứ hạng. Bài viết này sẽ hướng dẫn bạn cách thực hiện điều đó.
Sử dụng Biến Người Dùng (User-Defined Variables)
MySQL hỗ trợ các biến người dùng, cho phép chúng ta tạo ra hành vi tương tự như hàm RANK() của các cơ sở dữ liệu khác.
Ví dụ 1: Tính xếp hạng các sinh viên theo điểm số
Giả sử ta có một bảng students
với các cột id
, name
và score
.
+----+-------+-------+
| id | name | score |
+----+-------+-------+
| 1 | John | 90 |
| 2 | Alice | 85 |
| 3 | Bob | 93 |
| 4 | Carol | 85 |
| 5 | Dave | 60 |
+----+-------+-------+
Chúng ta muốn xếp hạng các sinh viên theo score
từ cao xuống thấp.
SET @rank = 0;
SELECT
id,
name,
score,
(@rank := @rank + 1) AS rank
FROM
students
ORDER BY
score DESC;
Kết quả sẽ là:
+----+-------+-------+------+
| id | name | score | rank |
+----+-------+-------+------+
| 3 | Bob | 93 | 1 |
| 1 | John | 90 | 2 |
| 2 | Alice | 85 | 3 |
| 4 | Carol | 85 | 4 |
| 5 | Dave | 60 | 5 |
+----+-------+-------+------+
Tính Thứ Hạng Với Điều Kiện
Trong trường hợp có các giá trị giống nhau và bạn muốn các giá trị đó được xếp hạng như nhau, phương pháp trên sẽ không hoàn toàn phù hợp. Để xử lý tình huống này, ta cần sử dụng một phương pháp khác.
Ví dụ 2: Xếp hạng các sinh viên với các số điểm giống nhau
SET @rank = 0;
SET @prev_score = NULL;
SELECT
id,
name,
score,
CASE
WHEN @prev_score = score THEN @rank
WHEN @prev_score := score THEN @rank := @rank + 1
ELSE @rank := @rank + 1
END AS rank
FROM
students
ORDER BY
score DESC;
Kết quả sẽ như sau:
+----+-------+-------+------+
| id | name | score | rank |
+----+-------+-------+------+
| 3 | Bob | 93 | 1 |
| 1 | John | 90 | 2 |
| 2 | Alice | 85 | 3 |
| 4 | Carol | 85 | 3 |
| 5 | Dave | 60 | 4 |
+----+-------+-------+------+
Sử dụng CTE
Với MySQL 8.0 trở lên, ta có thể sử dụng CTE (Common Table Expressions) để tạo cách tính thứ hạng dễ đọc hơn.
Ví dụ 3: Sử dụng CTE để tính xếp hạng
WITH ranked_students AS (
SELECT
id,
name,
score,
DENSE_RANK() OVER (ORDER BY score DESC) AS rank
FROM
students
)
SELECT * FROM ranked_students;
Kết quả sẽ là:
+----+-------+-------+------+
| id | name | score | rank |
+----+-------+-------+------+
| 3 | Bob | 93 | 1 |
| 1 | John | 90 | 2 |
| 2 | Alice | 85 | 3 |
| 4 | Carol | 85 | 3 |
| 5 | Dave | 60 | 4 |
+----+-------+-------+------+
Kết Luận
Mặc dù MySQL không có hàm RANK() như một số hệ quản trị cơ sở dữ liệu khác, nhưng nhờ vào các biến người dùng, phương pháp tính với điều kiện và các tính năng của CTE trong MySQL 8.0 trở lên, chúng ta vẫn có thể dễ dàng tính toán thứ hạng cho các bản ghi trong bảng. Hy vọng bài viết này cung cấp cho bạn các giải pháp hữu ích để áp dụng vào dự án thực tế của mình.
Comments