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

Sådan fungerer DENSE_RANK() i SQL Server

I SQL Server er DENSE_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 distinkte rækker, der kommer før rækken.

Denne funktion ligner RANK() , men uden de huller i rangeringsværdierne, der kan forekomme med RANK() når der er bånd i resultatsættet.

Syntaks

Syntaksen ser sådan ud:

DENSE_RANK ( ) OVER ( [  ] < order_by_clause > )

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

er påkrævet. Det bestemmer den rækkefølge, som funktionen gælder for rækkerne i en partition.

Bemærk, at OVER klausul accepterer normalt en , men det argument kan ikke bruges med denne funktion.

Eksempel 1 – Grundlæggende brug

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

SELECT
  AlbumId,
  AlbumName,
  ArtistId,
  DENSE_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          | 2      |
| 19        | All Night Wrong          | 3          | 3      |
| 20        | The Sixteen Men of Tain  | 3          | 3      |
| 12        | Big Swing Face           | 4          | 4      |
| 4         | Ziltoid the Omniscient   | 5          | 5      |
| 5         | Casualties of Cool       | 5          | 5      |
| 6         | Epicloud                 | 5          | 5      |
| 3         | Singing Down the Lane    | 6          | 6      |
| 16        | Long Lost Suitcase       | 7          | 7      |
| 17        | Praise and Blame         | 7          | 7      |
| 18        | Along Came Jones         | 7          | 7      |
| 11        | No Sound Without Silence | 9          | 8      |
| 21        | Yo Wassup                | 9          | 8      |
| 22        | Busted                   | 9          | 8      |
| 13        | Blue Night               | 12         | 9      |
| 14        | Eternity                 | 12         | 9      |
| 15        | Scandinavia              | 12         | 9      |
+-----------+--------------------------+------------+--------+

Se på ArtistId og Rank kolonner. Rangeringen stiger hver gang ArtistId øges. Dette skyldes, at jeg bestiller efter ArtistId, og så vil hver ny kunstner få en ny rang.

Rangeringen forbliver den samme for hver kunstner, uanset hvor mange rækker der indeholder det samme ArtistId, fordi resultaterne er sorteret efter den kolonne. For eksempel indeholder fem rækker det samme ArtistId og derfor indeholder de også den samme rang. Med andre ord er de alle uafgjort til rang 1.

I mange rækker er rangeringen tilfældigvis identisk med ArtistId, men dette er kun en tilfældighed. Tilfældigvis er ArtistId en IDENTITY kolonne, der starter med 1 og stiger med 1, hvilket også er hvad RANK() gør. Du vil dog se, at de ikke er identiske på alle rækker. For eksempel springer ArtistId fra 7 til 9, men rangeringen stiger simpelthen fra 7 til 8, og fra det tidspunkt indeholder begge kolonner forskellige værdier.

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,
  DENSE_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          | 2      |
| Pop     | Long Lost Suitcase       | 7          | 1      |
| Pop     | Praise and Blame         | 7          | 1      |
| Pop     | Along Came Jones         | 7          | 1      |
| Pop     | No Sound Without Silence | 9          | 2      |
| Pop     | Blue Night               | 12         | 3      |
| Pop     | Eternity                 | 12         | 3      |
| Pop     | Scandinavia              | 12         | 3      |
| 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          | 2      |
| Rock    | Ziltoid the Omniscient   | 5          | 3      |
| Rock    | Casualties of Cool       | 5          | 3      |
| Rock    | Epicloud                 | 5          | 3      |
+---------+--------------------------+------------+--------+

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,
  DENSE_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 opmærksom på, at eventuelle uafhængige resultater ikke vil påvirke efterfølgende rækker. Med andre ord vil der ikke være huller i rangværdien.

Dette forklares nok bedst med et eksempel:

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

I dette tilfælde er Lisa og Bart uafgjort på nummer 1. Så kommer Burns ind på nummer 2 (selvom han er den tredje person).

Hvis du foretrækker, at Burns blev rangeret som nummer 3 i dette tilfælde (og Meg på 4, og så videre), skal du bruge RANK() funktion i stedet for.

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

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

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

  1. Sådan fungerer DATEDIFF() i MariaDB

  2. Konverter hex i tekstrepræsentation til decimaltal

  3. Hvad gør (+) i Oracle SQL?

  4. Få envelope, dvs. overlappende tidsrum