Trong quá trình làm việc với dữ liệu, chúng ta thường xuyên phát sinh những nhu cầu cần sắp xếp hoặc xếp hạng cho một thực thể nào đó. Chúng ta có thể sử dụng 3 hàm xếp hạng trong SQL điển hình là: ROW_NUMBER, RANK và DENSE_RANK. Chúng là những công cụ mạnh mẽ, mang lại sự linh hoạt trong việc sắp xếp thông tin, nhưng chúng cũng đồng thời có những sự khác biệt quan trọng.
Vậy đặc điểm mỗi hàm là gì, sự khác biệt giữa chúng cụ thể như thế nào và làm sao để tận dụng hết tiềm năng của các hàm trong công việc xử lý dữ liệu, các bạn cùng Datapot tìm hiểu ngay sau đây nhé!
Mục lục
Hàm Row_Number()
Định nghĩa và cú pháp
ROW_NUMBER() là một hàm trong SQL được sử dụng để xếp hạng các bản ghi trong một tập kết quả, KHÔNG quan tâm giá trị ở các bản ghi đó là giống hay khác nhau.
Hàm này thường đi kèm với mệnh đề OVER để xác định phạm vi của việc đánh số. Cú pháp cơ bản của ROW_NUMBER() như sau:
ROW_NUMBER() OVER (ORDER BY column1, column2, ...)
Trong đó:
- ORDER BY: Xác định cột hoặc danh sách các cột mà dựa trên đó dữ liệu sẽ được sắp xếp.
- column1, column2, …: Các cột sẽ được sử dụng để xác định thứ tự sắp xếp.
Đặc điểm
ROW_NUMBER() sẽ gán một thứ hạng duy nhất cho mỗi bản ghi tùy thuộc vào thứ tự sắp xếp. Tức là, khi có các giá trị bằng nhau, ROW_NUMBER() sẽ gán thứ hạng một cách tuần tự theo thứ tự xuất hiện của dữ liệu, nếu có nhiều bản ghi có giá trị sắp xếp theo cột đã chọn là bằng nhau, thì sẽ không có sự phân biệt giữa chúng mà sẽ gán số thứ tự tăng dần dựa trên thứ tự xuất hiện trong kết quả sắp xếp.
Ví dụ
Yêu cầu:
Sắp xếp vị trí của mỗi nhân viên trong danh sách theo thứ tự nhân viên có VacationHours (giả sử VacationHours là thông tin về số giờ nghỉ phép của nhân viên) giảm dần.
Cú pháp sử dụng:
SELECT
DISTINCT FirstName,
VacationHours,
ROW_NUMBER() OVER (ORDER BY VacationHours DESC) AS RowNumber
FROM DimEmployee
ORDER BY RowNumber;
Kết quả:

Giải thích kết quả:
Ken, Chad và Betsy đều có giá trị VacationHours bằng 99, giá trị của row_num (cột RowNumber) cũng vẫn tăng lên, giá trị của row_num không hề bị lặp lại và phụ thuộc vào vị trí sắp xếp của từng bạn trong hàm row_num, tương ứng với Ken = 1, Chad = 2, Betsy = 3 (row_num tăng dần theo chiều Alphabet giảm dần).
Hàm Rank()
Định nghĩa và cú pháp
RANK() là một hàm xếp hạng được sử dụng để gán một thứ hạng cho mỗi bản ghi trong một tập kết quả dựa trên một tiêu chí sắp xếp cụ thể.
Giống như ROW_NUMBER(), thì RANK() cũng đi kèm với mệnh đề OVER để xác định phạm vi của việc đánh số.
Cú pháp cơ bản của như sau:
RANK() OVER (ORDER BY column1, column2, ...)
Trong đó:
- ORDER BY: Xác định cột hoặc danh sách các cột mà dựa trên đó dữ liệu sẽ được sắp xếp.
- column1, column2, …: Các cột sẽ được sử dụng để xác định thứ tự sắp xếp.
Đặc điểm
Kết quả của hàm RANK() là một thứ hạng duy nhất cho mỗi bản ghi, bắt đầu từ 1 và tăng dần theo thứ tự xuất hiện trong kết quả sắp xếp. Nếu có các giá trị bằng nhau, thì các dòng có giá trị giống nhau sẽ nhận cùng một số xếp hạng, và số xếp hạng tiếp theo sẽ bị bỏ qua (không tăng liên tục).
Ví dụ cụ thể
Yêu cầu:
Sắp xếp vị trí của mỗi nhân viên trong danh sách theo thứ tự nhân viên có VacationHours (giả sử VacationHours là thông tin về số giờ nghỉ phép của nhân viên) giảm dần.
Cú pháp sử dụng:
SELECT
DISTINCT FirstName,
VacationHours,
RANK() OVER (ORDER BY VacationHours DESC) AS Row_Number
FROM DimEmployee
ORDER BY RowNumber;
Kết quả:

Giải thích:
Khác với ROW_NUMBER() khi nãy là Ken, Chad và Betsy đều có giá trị VacationHours bằng 99 thì giá trị của row_num (cột RowNumber) cũng vẫn tăng lên (tương ứng là 1, 2, 3) tuy nhiên khi sắp xếp bằng hàm RANK() có sự khác biệt đó là, giá trị của row_num của 03 bạn Ken, Chad và Betsy đều bằng 1.
Bạn có VacationHours liền tiếp đó là Kim (VacationHours = 98) được xếp hạng 4, bỏ qua hạng 2,3 (ứng với 02 bạn có giá trị đồng hạng 1).
Hàm Dense_Rank()
Định nghĩa và cú pháp
Tương tự ROW_NUMBER() và RANK(), DENSE_RANK() cũng là một hàm xếp hạng được sử dụng để gán một thứ hạng cho mỗi bản ghi trong một tập kết quả dựa trên một tiêu chí sắp xếp cụ thể. Tuy nhiên, nó không bỏ qua số xếp hạng khi có các giá trị bằng nhau.
DENSE_RANK() đi kèm với mệnh đề OVER để xác định phạm vi của việc đánh số. Cú pháp cơ bản của như sau:
DENSE_RANK() OVER (ORDER BY column1, column2, ...)
Trong đó:
- ORDER BY: Xác định cột hoặc danh sách các cột mà dựa trên đó dữ liệu sẽ được sắp xếp.
- column1, column2, …: Các cột sẽ được sử dụng để xác định thứ tự sắp xếp.
Đặc điểm
Kết quả của hàm DENSE_RANK() là một thứ hạng duy nhất cho mỗi bản ghi, bắt đầu từ 1 và tăng dần theo thứ tự xuất hiện trong kết quả sắp xếp. Tuy nhiên DENSE_RANK() khác RANK() ở chỗ, nếu có các giá trị bằng nhau, thì các dòng có giá trị giống nhau sẽ nhận cùng một số xếp hạng, và số xếp hạng tiếp theo sẽ tăng liên tục mà không bị bỏ qua.
Ví dụ cụ thể
Yêu cầu:
Sắp xếp vị trí của mỗi nhân viên trong danh sách theo thứ tự nhân viên có VacationHours (giả sử VacationHours là thông tin về số giờ nghỉ phép của nhân viên) giảm dần.
Cú pháp sử dụng:
SELECT
DISTINCT FirstName,
VacationHours,
DENSE_RANK() OVER (ORDER BY VacationHours DESC) AS RowNumber
FROM DimEmployee
ORDER BY RowNumber;
Kết quả:

Giải thích:
Giống với RANK() là Ken, Chad và Betsy đều có giá trị VacationHours bằng 99 thì giá trị của row_num (cột RowNumber) đều trả về bằng 1. Tuy nhiên do DENSE_RANK() không bỏ qua số xếp hạng tiếp theo nên bạn có VacationHours liền tiếp đó là Kim (VacationHours = 98) được xếp hạng 2, hay có thể hiểu Kim là người có giá mốc giá trị VacationHours cao thứ hai trong tập dữ liệu (ba bạn Ken, Chad và Betsy cùng mang mốc giá trị cao nhất).
So sánh 3 hàm
Ví dụ tổng quan cả 3 trường hợp

Bảng so sánh
Tiêu chí | ROW_NUMBER() | RANK() | DENSE_RANK() | |
Giống nhau | Xếp hạng dữ liệu | Gán số xếp hạng là duy nhất cho mỗi bản ghi (tức là ứng với mỗi bản ghi chỉ có 1 xếp hạng) | ||
Chiều xếp hạng | Bắt đầu từ 1, sắp xếp tăng dần | |||
Khác nhau | Sắp xếp bản ghi có giá trị bằng nhau | Số xếp hạng tăng liên tục. | Bỏ qua số xếp hạng tiếp theo khi giá trị giống nhau. | Số xếp hạng tăng liên tục khi giá trị giống nhau. Không bỏ qua số xếp hạng tiếp theo khi giá trị giống nhau. |
Như vậy là chúng ta đã nắm được sự giống và khác nhau của 03 loại hàm xếp hạng trên. Chúc các bạn có thể áp dụng vào bài học và công việc trên thực tế.
Để thực hành và cập nhật thêm nhiều kiến thức về SQL, các bạn có thể tham khảo thêm các bài viết tại SQL Archives – Datapot.vn
Cảm ơn các bạn!

CEO & Founder Datapot
Microsoft Solution Expert, Microsoft Certified Trainer