Trong SQL Server, RANK()
hàm trả về thứ hạng của mỗi hàng trong phân vùng của tập kết quả. Thứ hạng của một hàng là một cộng với số bậc đứng trước hàng.
Cú pháp
Cú pháp như sau:
RANK ( ) OVER ( [ partition_by_clause ] order_by_clause )
partition_by_clause Là tùy chọn. Nó chia tập hợp kết quả được tạo ra bởi FROM
mệnh đề thành các phân vùng mà hàm được áp dụng. Nếu không được chỉ định, hàm sẽ coi tất cả các hàng của tập kết quả truy vấn là một nhóm duy nhất.
order_by_clause bắt buộc. Nó xác định thứ tự của dữ liệu trước khi chức năng được áp dụng.
Lưu ý rằng OVER
mệnh đề thường chấp nhận một rows_or_range_clause , nhưng không thể sử dụng đối số đó với RANK()
chức năng.
Ví dụ 1 - Cách sử dụng cơ bản
Dưới đây là một ví dụ cơ bản cho thấy cách sử dụng RANK()
chức năng:
SELECT AlbumId, AlbumName, ArtistId, RANK() OVER (ORDER BY ArtistId ASC) 'Rank' FROM Albums;
Kết quả:
+-----------+--------------------------+------------+--------+ | AlbumId | AlbumName | ArtistId | Rank | |-----------+--------------------------+------------+--------| | 1 | Powerslave | 1 | 1 | | 7 | Somewhere in Time | 1 | 1 | | 8 | Piece of Mind | 1 | 1 | | 9 | Killers | 1 | 1 | | 10 | No Prayer for the Dying | 1 | 1 | | 2 | Powerage | 2 | 6 | | 19 | All Night Wrong | 3 | 7 | | 20 | The Sixteen Men of Tain | 3 | 7 | | 12 | Big Swing Face | 4 | 9 | | 4 | Ziltoid the Omniscient | 5 | 10 | | 5 | Casualties of Cool | 5 | 10 | | 6 | Epicloud | 5 | 10 | | 3 | Singing Down the Lane | 6 | 13 | | 16 | Long Lost Suitcase | 7 | 14 | | 17 | Praise and Blame | 7 | 14 | | 18 | Along Came Jones | 7 | 14 | | 11 | No Sound Without Silence | 9 | 17 | | 21 | Yo Wassup | 9 | 17 | | 22 | Busted | 9 | 17 | | 13 | Blue Night | 12 | 20 | | 14 | Eternity | 12 | 20 | | 15 | Scandinavia | 12 | 20 | +-----------+--------------------------+------------+--------+
Trọng tâm chính của chúng tôi là ArtistId và Xếp hạng cột. Chúng ta có thể thấy rằng thứ hạng tăng lên mỗi khi ArtistId tăng. Điều này là do tôi đang đặt hàng theo ArtistId nên mỗi nghệ sĩ mới sẽ nhận được một thứ hạng mới.
Khi chúng tôi xem xét Xếp hạng , chúng ta có thể thấy khá nhiều mối quan hệ. Có nghĩa là, khá nhiều hàng có cùng thứ hạng. Điều này có thể xảy ra vì tôi đang đặt hàng theo ArtistId và một số giá trị ArtistId nằm trong nhiều hàng.
Các hàng liên kết này rất hữu ích để chứng minh cách RANK()
làm. Như đã đề cập, nó tăng thêm một cộng với số thứ hạng đứng trước nó. Các hàng được ràng buộc khiến khoảng trống xuất hiện trong các giá trị xếp hạng (tức là chúng không phải lúc nào cũng tăng 1). Trong ví dụ trên, có khá nhiều khoảng trống. Đầu tiên là nơi nó đi từ 1 đến 6. Sau đó, một cái khác khi nó đi từ 7 đến 9, v.v.
Nếu bạn không muốn những khoảng trống này, hãy sử dụng DENSE_RANK()
, hoạt động theo cùng một cách ngoại trừ không có khoảng trống. Thứ hạng dày đặc được tính bằng một cộng với số phân biệt xếp hạng các giá trị đứng trước hàng đó.
Ví dụ 2 - Phân vùng
Bạn cũng có thể chia kết quả thành các phân vùng. Khi bạn làm điều này, thứ hạng được tính dựa trên mỗi phân vùng (vì vậy nó sẽ bắt đầu lại với mỗi phân vùng mới).
Ví dụ:
SELECT Genre, AlbumName, ArtistId, RANK() OVER (PARTITION BY Genre ORDER BY ArtistId ASC) 'Rank' FROM Albums INNER JOIN Genres ON Albums.GenreId = Genres.GenreId;
Kết quả:
+---------+--------------------------+------------+--------+ | Genre | AlbumName | ArtistId | Rank | |---------+--------------------------+------------+--------| | Country | Singing Down the Lane | 6 | 1 | | Country | Yo Wassup | 9 | 2 | | Country | Busted | 9 | 2 | | Jazz | All Night Wrong | 3 | 1 | | Jazz | The Sixteen Men of Tain | 3 | 1 | | Jazz | Big Swing Face | 4 | 3 | | Pop | Long Lost Suitcase | 7 | 1 | | Pop | Praise and Blame | 7 | 1 | | Pop | Along Came Jones | 7 | 1 | | Pop | No Sound Without Silence | 9 | 4 | | Pop | Blue Night | 12 | 5 | | Pop | Eternity | 12 | 5 | | Pop | Scandinavia | 12 | 5 | | Rock | Powerslave | 1 | 1 | | Rock | Somewhere in Time | 1 | 1 | | Rock | Piece of Mind | 1 | 1 | | Rock | Killers | 1 | 1 | | Rock | No Prayer for the Dying | 1 | 1 | | Rock | Powerage | 2 | 6 | | Rock | Ziltoid the Omniscient | 5 | 7 | | Rock | Casualties of Cool | 5 | 7 | | Rock | Epicloud | 5 | 7 | +---------+--------------------------+------------+--------+
Trong trường hợp này, tôi phân vùng theo Thể loại. Điều này khiến mỗi hàng chỉ được xếp hạng so với các hàng khác trong cùng một phân vùng. Vì vậy, mỗi phân vùng làm cho giá trị xếp hạng bắt đầu lại từ 1.
Ví dụ 3 - Ví dụ về Bảng điểm
Đây là một trường hợp sử dụng khả thi để hiển thị thứ hạng cho người dùng.
SELECT Player, Score, RANK() OVER (ORDER BY Score Desc) 'Rank' FROM Scoreboard;
Kết quả:
+----------+---------+--------+ | Player | Score | Rank | |----------+---------+--------| | Bart | 2010 | 1 | | Burns | 1270 | 2 | | Meg | 1030 | 3 | | Marge | 990 | 4 | | Lisa | 710 | 5 | | Ned | 666 | 6 | | Apu | 350 | 7 | | Homer | 1 | 8 | +----------+---------+--------+
Tuy nhiên, hãy lưu ý rằng bất kỳ kết quả ràng buộc nào cũng sẽ dẫn đến khoảng cách trong các giá trị xếp hạng.
Dưới đây là những gì sẽ xảy ra nếu Lisa bất ngờ khớp với điểm của Bart:
SELECT Player, Score, RANK() OVER (ORDER BY Score Desc) 'Rank' FROM Scoreboard;
Kết quả:
+----------+---------+--------+ | Player | Score | Rank | |----------+---------+--------| | Lisa | 2010 | 1 | | Bart | 2010 | 1 | | Burns | 1270 | 3 | | Meg | 1030 | 4 | | Marge | 990 | 5 | | Ned | 666 | 6 | | Apu | 350 | 7 | | Homer | 1 | 8 | +----------+---------+--------+
Trong trường hợp này, không ai được xếp ở vị trí thứ 2, bởi vì hai người chơi đầu tiên đang xếp ở vị trí thứ 1.
Như đã đề cập, nếu bạn cần loại bỏ các khoảng trống như khoảng trống này, hãy sử dụng DENSE_RANK()
.
Ví dụ 4 - Thay thế RANK () bằng DENSE_RANK ()
Đây là ví dụ tương tự một lần nữa, ngoại trừ lần này tôi sử dụng DENSE_RANK()
:
SELECT Player, Score, DENSE_RANK() OVER (ORDER BY Score Desc) 'Rank' FROM Scoreboard;
Kết quả:
+----------+---------+--------+ | Player | Score | Rank | |----------+---------+--------| | Lisa | 2010 | 1 | | Bart | 2010 | 1 | | Burns | 1270 | 2 | | Meg | 1030 | 3 | | Marge | 990 | 4 | | Ned | 666 | 5 | | Apu | 350 | 6 | | Homer | 1 | 7 | +----------+---------+--------+