sql >> Database >  >> RDS >> Database

Overeenkomsten en verschillen tussen RANK-, DENSE_RANK- en ROW_NUMBER-functies

De functies RANK, DENSE_RANK en ROW_NUMBER worden gebruikt om een ​​toenemende integerwaarde op te halen. Ze beginnen met een waarde die is gebaseerd op de voorwaarde die wordt opgelegd door de ORDER BY-clausule. Voor al deze functies is de ORDER BY-clausule vereist om correct te kunnen functioneren. In het geval van gepartitioneerde gegevens, wordt de teller voor gehele getallen voor elke partitie op 1 gezet.

In dit artikel zullen we de functies RANK, DENSE_RANK en ROW_NUMBER in detail bestuderen, maar laten we eerst dummy-gegevens maken waarop deze functies kunnen worden gebruikt, tenzij er een volledige back-up van uw database is gemaakt.

Dummy-gegevens voorbereiden

Voer het volgende script uit om een ​​database te maken met de naam ShowRoom en die een tabel Cars bevat (die 15 willekeurige records van auto's bevat):

CREATE Database ShowRoom;
GO
USE ShowRoom;

CREATE TABLE Cars
(
id INT,
name VARCHAR(50) NOT NULL,
company VARCHAR(50) NOT NULL,
power INT NOT NULL
)


USE ShowRoom
INSERT INTO Cars
VALUES
(1, 'Corrolla', 'Toyota', 1800),
(2, 'City', 'Honda', 1500),
(3, 'C200', 'Mercedez', 2000),
(4, 'Vitz', 'Toyota', 1300),
(5, 'Baleno', 'Suzuki', 1500),
(6, 'C500', 'Mercedez', 5000),
(7, '800', 'BMW', 8000),
(8, 'Mustang', 'Ford', 5000),
(9, '208', 'Peugeot', 5400),
(10, 'Prius', 'Toyota', 3200),
(11, 'Atlas', 'Volkswagen', 5000),
(12, '110', 'Bugatti', 8000),
(13, 'Landcruiser', 'Toyota', 3000),
(14, 'Civic', 'Honda', 1800),
(15, 'Accord', 'Honda', 2000)

RANK-functie

De RANK-functie wordt gebruikt om gerangschikte rijen op te halen op basis van de voorwaarde van de ORDER BY-clausule. Als u bijvoorbeeld de naam van de auto met het op twee na hoogste vermogen wilt vinden, kunt u de RANK-functie gebruiken.
Laten we de RANK-functie in actie bekijken:

SELECT name,company, power,
RANK() OVER(ORDER BY power DESC) AS PowerRank
FROM Cars

Het bovenstaande script zoekt en rangschikt alle records in de Cars-tabel en rangschikt ze in volgorde van afnemende kracht. De uitvoer ziet er als volgt uit:

De PowerRank-kolom in de bovenstaande tabel bevat de RANK van de auto's, gerangschikt in aflopende volgorde van hun vermogen. Een interessant aspect van de RANK-functie is dat als er een gelijkspel is tussen N eerdere records voor de waarde in de ORDER BY-kolom, de RANK-functies de volgende N-1 posities overslaan voordat de teller wordt verhoogd. In het bovenstaande resultaat is er bijvoorbeeld een gelijkspel voor de waarden in de machtskolom tussen de 1e en 2e rij, daarom slaat de RANK-functie het volgende (2-1 =1) record over en springt direct naar de 3e rij.
De RANK-functie kan worden gebruikt in combinatie met de PARTITION BY-clausule. In dat geval wordt de rangorde voor elke nieuwe partitie opnieuw ingesteld. Bekijk het volgende script:

SELECT name,company, power,
RANK() OVER(PARTITION BY company ORDER BY power DESC) AS PowerRank
FROM Cars

In het bovenstaande script verdelen we de resultaten per bedrijfskolom. Voor elk bedrijf wordt de RANG nu teruggezet naar 1 zoals hieronder weergegeven:

DENSE_RANK-functie

De DENSE_RANK-functie is vergelijkbaar met de RANK-functie, maar de DENSE_RANK-functie slaat geen rangen over als er een gelijkspel is tussen de rangen van de voorgaande records. Bekijk het volgende script.

SELECT name,company, power,
RANK() OVER(PARTITION BY company ORDER BY power DESC) AS PowerRank
FROM Cars

U kunt aan de uitvoer zien dat ondanks dat er een gelijkspel is tussen de rangen van de eerste twee rijen, de volgende rang niet wordt overgeslagen en een waarde van 2 heeft gekregen in plaats van 3. Net als bij de RANK-functie, kan de PARTITION BY-component kan ook worden gebruikt met de DENSE_RANK-functie zoals hieronder getoond:

SELECT name,company, power,
DENSE_RANK() OVER(PARTITION BY company ORDER BY power DESC) AS DensePowerRank
FROM Cars

ROW_NUMBER Functie

In tegenstelling tot de functies RANK en DENSE_RANK, retourneert de functie ROW_NUMBER eenvoudig het rijnummer van de gesorteerde records beginnend met 1. Als de functies RANK en DENSE_RANK van de eerste twee records in de ORDER BY-kolom bijvoorbeeld gelijk zijn, wordt aan beide een 1 toegewezen. als hun RANK en DENSE_RANK. De functie ROW_NUMBER wijst echter waarden 1 en 2 toe aan die rijen zonder rekening te houden met het feit dat ze gelijkelijk in aanmerking worden genomen. Voer het volgende script uit om de ROW_NUMBER-functie in actie te zien.

SELECT name,company, power,
ROW_NUMBER() OVER(ORDER BY power DESC) AS RowRank
FROM Cars

Uit de uitvoer kunt u zien dat de ROW_NUMBER-functie eenvoudig een nieuw rijnummer toewijst aan elke record, ongeacht de waarde.
De PARTITION BY-component kan ook worden gebruikt met de ROW_NUMBER-functie, zoals hieronder weergegeven:

SELECT name, company, power,
ROW_NUMBER() OVER(PARTITION BY company ORDER BY power DESC) AS RowRank
FROM Cars

De uitvoer ziet er als volgt uit:

Overeenkomsten tussen RANK-, DENSE_RANK- en ROW_NUMBER-functies

De functies RANK, DENSE_RANK en ROW_NUMBER hebben de volgende overeenkomsten:
1- Ze vereisen allemaal een order by-clausule.
2- Ze retourneren allemaal een oplopend geheel getal met een basiswaarde van 1.
3- In combinatie met een PARTITION BY-clausule, resetten al deze functies de geretourneerde integerwaarde naar 1 zoals we hebben gezien.
4- Als er geen dubbele waarden zijn in de kolom die wordt gebruikt door de ORDER BY-clausule, zijn deze functies retourneren dezelfde uitvoer.
Om het laatste punt te illustreren, maken we een nieuwe tabel Car1 in de ShowRoom-database zonder dubbele waarden in de power-kolom. Voer het volgende script uit:

USE ShowRoom;

CREATE TABLE Cars1
(
id INT,
name VARCHAR(50) NOT NULL,
company VARCHAR(50) NOT NULL,
power INT NOT NULL
)


INSERT INTO Cars1
VALUES
(1, 'Corrolla', 'Toyota', 1800),
(2, 'City', 'Honda', 1500),
(3, 'C200', 'Mercedez', 2000),
(4, 'Vitz', 'Toyota', 1300),
(5, 'Baleno', 'Suzuki', 2500),
(6, 'C500', 'Mercedez', 5000),
(7, '800', 'BMW', 8000),
(8, 'Mustang', 'Ford', 4000),
(9, '208', 'Peugeot', 5400),
(10, 'Prius', 'Toyota', 3200)
The cars1 table has no duplicate values. Now let’s execute the RANK, DENSE_RANK and ROW_NUMBER functions on the Cars1 table ORDER BY power column. Execute the following script:
SELECT name,company, power,
RANK() OVER(ORDER BY power DESC) AS [Rank],
DENSE_RANK() OVER(ORDER BY power DESC) AS [Dense Rank],
ROW_NUMBER() OVER(ORDER BY power DESC) AS [Row Number]
FROM Cars1

De uitvoer ziet er als volgt uit:

U kunt zien dat er geen dubbele waarden zijn in de machtskolom die wordt gebruikt in de ORDER BY-component, daarom is de uitvoer van de functies RANK, DENSE_RANK en ROW_NUMBER hetzelfde.

Verschil tussen RANK-, DENSE_RANK- en ROW_NUMBER-functies

Het enige verschil tussen de RANK-, DENSE_RANK- en ROW_NUMBER-functie is wanneer er dubbele waarden zijn in de kolom die wordt gebruikt in ORDER BY-clausule.
Als u teruggaat naar de Cars-tabel in de ShowRoom-database, ziet u dat deze veel dubbele waarden. Laten we proberen de RANK, DENSE_RANK en ROW_NUMBER van de Cars1-tabel te vinden, gerangschikt op vermogen. Voer het volgende script uit:
SELECT name,company, power,

RANK() OVER(ORDER BY power DESC) AS [Rank],
DENSE_RANK() OVER(ORDER BY power DESC) AS [Dense Rank],
ROW_NUMBER() OVER(ORDER BY power DESC) AS [Row Number]
FROM Cars

De uitvoer ziet er als volgt uit:

Uit de uitvoer kunt u zien dat de RANK-functie de volgende N-1 rangen overslaat als er een gelijkspel is tussen N vorige rangen. Aan de andere kant slaat de functie DENSE_RANK geen rangen over als er een gelijkspel is tussen de rangen. Ten slotte heeft de functie ROW_NUMBER geen betrekking op rangschikking. Het retourneert eenvoudig het rijnummer van de gesorteerde records. Zelfs als er dubbele records zijn in de kolom die wordt gebruikt in de ORDER BY-component, retourneert de functie ROW_NUMBER geen dubbele waarden. In plaats daarvan zal het blijven toenemen, ongeacht de dubbele waarden.

Nuttige links:

Lees het fantastische artikel van Ahmad Yaseen voor meer informatie over ROW_NUMBER(), RANK() en DENSE_RANK() functies:

Methoden om rijen in SQL Server te rangschikken:ROW_NUMBER(), RANK(), DENSE_RANK() en NTILE()


  1. Snelle tip – Versnel een langzaam herstel vanuit het transactielogboek

  2. Kan ik negeer_dup_key inschakelen voor een primaire sleutel?

  3. De aggregatie-operator voor vermenigvuldiging in SQL

  4. SQLException:Protocolschending. Probleem met Oracle JDBC-stuurprogramma