Row_number, Rank, Dense_rank khác biệt thế nào

Đôi lúc bạn có thể nhầm giữa 3 lệnh này vì chúng đều đánh số dữ liệu theo 1 tuần tự.Tuy nhiên mục đích sử dụng và ý nghĩa của 3 lệnh này hoàn toàn khác nhau. Mình sẽ phân biệt trong bài viết bên dưới.

Row_number, Rank, Dense_rank khác biệt thế nào

Row_number

Row number đơn giản là… đánh số của từng dòng theo nghĩa nguyên thủy nhất. Tức là dữ liệu của bạn được đánh số theo thứ tự cố định theo thứ tự sẵn có của một cột, sau đây là ví dụ. Bạn có thể thấy dữ liệu được đánh số theo thứ tự

WITH Numbers AS
 (SELECT 1 as x
  UNION ALL SELECT 2
  UNION ALL SELECT 2
  UNION ALL SELECT 5
  UNION ALL SELECT 8
  UNION ALL SELECT 10
  UNION ALL SELECT 10
)
SELECT x,
  ROW_NUMBER() OVER (ORDER BY x) AS row_num
FROM Numbers

+-------------------------+
| x          | row_num    |
+-------------------------+
| 1          | 1          |
| 2          | 2          |
| 2          | 3          |
| 5          | 4          |
| 8          | 5          |
| 10         | 6          |
| 10         | 7          |
+-------------------------+

Lưu ý: hãy để ý khi dữ liệu ở giá trị ’10’ bị lặp lại 2 lần, giá trị của row_num cũng vẫn tăng lên, giá trị của row_num không hề bị lặp lại và chỉ phụ thuộc vào vị trí sắp xếp của x trong hàm row_num.

Rank

Rank là hàm dùng để xếp hạng dữ liệu từ cao tới thấp (nghe giống row_number quá) tuy nhiên có một điểm cốt lõi làm rank khác row_number đó chính là rank sẽ có giá trị bị lặp lại khi data bị trùng lặp, không như row_number. Giả sử bạn có giá trị 10 2 lần -> cả 2 dòng có giá trị 10 đều có cùng giá trị rank là 6 10-10 : 6-6. Ví dụ cụ thể dưới đây.

WITH Numbers AS
 (SELECT 1 as x
  UNION ALL SELECT 2
  UNION ALL SELECT 2
  UNION ALL SELECT 5
  UNION ALL SELECT 8
  UNION ALL SELECT 10
  UNION ALL SELECT 10
)
SELECT x,
  RANK() OVER (ORDER BY x ASC) AS rank
FROM Numbers

+-------------------------+
| x          | rank       |
+-------------------------+
| 1          | 1          |
| 2          | 2          |
| 2          | 2          |
| 5          | 4          |
| 8          | 5          |
| 10         | 6          |
| 10         | 6          |
+-------------------------+

Lưu ý: bạn có để ý điều gì đặc biệt khi chạy rank không? đó chính là không có giá trị rank – 3 trong ví dụ trên các thứ tự là 1-2-4-5-6. Lí do điều này xảy ra vì rank đã có 2 lần lặp lại ở giá trị 2, có nghĩa là có 2 đồng hạng nhì, nên không có hạng 3 nữa, giống như trong các giải đấu thể thao vậy. Đây là điểm cốt lõi để phân biệt với dense rank dưới đây.

Dense_rank

Dense rank có logic về thứ tự giống như rank, tức là cũng đánh số theo thứ tự, và có giá trị lặp khi cột có giá trị bị lặp lại. Tuy nhiên điểm khác biệt chính của dense rank là không bỏ đi thứ hạng dù cho thứ hạng gần nhất bị lặp lại nhiều lần. Xét ví dụ rank phía trên bạn thấy hạng 2 xuất hiện 2 lần và vì thế không có hạng 3 nữa mà chỉ có hạng 4. Đối với dense rank thì vẫn có thể có 2 hạng nhì và hạng 3 riêng biệt bình thường. Ví dụ như dưới đây.

WITH Numbers AS
 (SELECT 1 as x
  UNION ALL SELECT 2
  UNION ALL SELECT 2
  UNION ALL SELECT 5
  UNION ALL SELECT 8
  UNION ALL SELECT 10
  UNION ALL SELECT 10
)
SELECT x,
  DENSE_RANK() OVER (ORDER BY x ASC) AS dense_rank
FROM Numbers

+-------------------------+
| x          | dense_rank |
+-------------------------+
| 1          | 1          |
| 2          | 2          |
| 2          | 2          |
| 5          | 3          |
| 8          | 4          |
| 10         | 5          |
| 10         | 5          |
+-------------------------+

Fun fact

Tại sao là Dense? Dense tức là dày đặt, bạn để ý nếu chúng ta sử dụng rank mà 1 thứ hạng bị chiếm nhiều lần quá thì khoảng cách giữa các giá trị rank sẽ bị kéo ra rất lớn. Giả sử có 200 người hạng nhì thì tất nhiên hạng 3 phải > 200. Trong khi đó nếu dùng dense_rank thì dù có 200 người hạng nhì đi nữa thì hạng 3 vẫn là hạng 3. Khoảng cách giữa các thứ hạng luôn là 1 và do đó nó gần hơn -> dày đặc hơn -> dense.

Support Tuan | Analytic

Trả lời