sql >> Database teknologi >  >> RDS >> Sqlserver

Hvordan RANK() virker i SQL Server

I SQL Server er RANK() funktion returnerer rangeringen af ​​hver række inden for partitionen af ​​et resultatsæt. Rangeringen af ​​en række er én plus antallet af rækker, der kommer før rækken.

Syntaks

Syntaksen ser sådan ud:

RANK ( ) OVER ( [ partition_by_clause ] order_by_clause )

partition_by_clause er valgfri. Den deler resultatsættet produceret af FROM klausul i partitioner, som funktionen anvendes på. Hvis det ikke er angivet, behandler funktionen alle rækker i forespørgselsresultatsættet som en enkelt gruppe.

ordre_by_clause er påkrævet. Det bestemmer rækkefølgen af ​​dataene, før funktionen anvendes.

Bemærk, at OVER klausul accepterer normalt en rows_or_range_clause , men det argument kan ikke bruges med RANK() funktion.

Eksempel 1 – Grundlæggende brug

Her er et grundlæggende eksempel, der viser brugen af ​​RANK() funktion:

SELECT
  AlbumId,
  AlbumName,
  ArtistId,
  RANK() OVER (ORDER BY ArtistId ASC) 'Rank'
FROM Albums;

Resultat:

+-----------+--------------------------+------------+--------+
| 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     |
+-----------+--------------------------+------------+--------+

Vores hovedfokus er ArtistId og Rank kolonner. Vi kan se, at rangeringen stiger, hver gang ArtistId'et stiger. Dette skyldes, at jeg bestiller efter ArtistId, og derfor vil hver ny kunstner få en ny rang.

Når vi ser på Rank kolonne, kan vi se en del bånd. Det vil sige, at en del rækker deler samme rang. Dette kan forventes, fordi jeg bestiller efter ArtistId, og nogle ArtistId-værdier er i mere end én række.

Disse bundne rækker er gode til at demonstrere hvordan RANK() arbejder. Som nævnt stiger den med én plus antallet af rækker, der kom før den. Sammenbundne rækker forårsager huller i rangeringsværdierne (dvs. de øges ikke altid med 1). I ovenstående eksempel er der en del huller. Den første er, hvor den går fra 1 til 6. Derefter en anden, når den går fra 7 til 9, og så videre.

Hvis du ikke vil have disse huller, skal du bruge DENSE_RANK() , som fungerer på samme måde undtagen uden huller. Den tætte rangering beregnes som én plus antallet af distinkte rangordne værdier, der kommer før denne række.

Eksempel 2 – Partitioner

Du kan også opdele resultaterne i partitioner. Når du gør dette, beregnes rangeringen mod hver partition (så den starter forfra med hver ny partition).

Eksempel:

SELECT
  Genre,
  AlbumName,
  ArtistId,
  RANK() OVER (PARTITION BY Genre ORDER BY ArtistId ASC) 'Rank'
FROM Albums
INNER JOIN Genres 
ON Albums.GenreId = Genres.GenreId;

Resultat:

+---------+--------------------------+------------+--------+
| 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      |
+---------+--------------------------+------------+--------+

I dette tilfælde opdeler jeg efter genre. Dette medfører, at hver række kun rangeres i forhold til de andre rækker i samme partition. Så hver partition får rangeringsværdien til at starte ved 1 igen.

Eksempel 3 – Et eksempel på resultattavlen

Her er en mulig use case til at vise rangeringen til brugeren.

SELECT  
  Player,
  Score,
  RANK() OVER (ORDER BY Score Desc) 'Rank'
FROM Scoreboard;

Resultat:

+----------+---------+--------+
| 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      |
+----------+---------+--------+

Vær dog opmærksom på, at eventuelle uafgjorte resultater vil resultere i huller i rangeringsværdierne.

Her er, hvad der sker, hvis Lisa pludselig matcher Barts score:

SELECT  
  Player,
  Score,
  RANK() OVER (ORDER BY Score Desc) 'Rank'
FROM Scoreboard;

Resultat:

+----------+---------+--------+
| 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      |
+----------+---------+--------+

I dette tilfælde er ingen rangeret som nummer 2, fordi de første to spillere er lige på rang 1.

Som nævnt, hvis du har brug for at fjerne huller som denne, skal du bruge DENSE_RANK() .

Eksempel 4 – Erstatning af RANK() med DENSE_RANK()

Her er det samme eksempel igen, bortset fra at denne gang bruger jeg DENSE_RANK() :

SELECT  
  Player,
  Score,
  DENSE_RANK() OVER (ORDER BY Score Desc) 'Rank'
FROM Scoreboard;

Resultat:

+----------+---------+--------+
| 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      |
+----------+---------+--------+

  1. Hvordan COERCIBILITY() virker i MariaDB

  2. Hvordan læser og opdaterer jeg SQLite-database ved hjælp af ListView i Android?

  3. Vil du hente kolonnenavne og typer af en lagret procedure?

  4. PostgreSQL multi INSERT...RETURNERER med flere kolonner