sql >> Databáze >  >> RDS >> Database

Podobnosti a rozdíly mezi funkcemi RANK, DENSE_RANK a ROW_NUMBER

Funkce RANK, DENSE_RANK a ROW_NUMBER se používají k načtení rostoucí celočíselné hodnoty. Začínají hodnotou založenou na podmínce uložené klauzuli ORDER BY. Všechny tyto funkce vyžadují ke správné funkci klauzuli ORDER BY. V případě rozdělených dat se celočíselné počítadlo vynuluje na 1 pro každý oddíl.

V tomto článku podrobně prostudujeme funkce RANK, DENSE_RANK a ROW_NUMBER, ale předtím si vytvořte fiktivní data, na kterých lze tyto funkce použít, pokud vaše databáze není plně zálohovaná.

Příprava fiktivních dat

Spusťte následující skript pro vytvoření databáze s názvem ShowRoom a obsahující tabulku nazvanou Cars (která obsahuje 15 náhodných záznamů automobilů):

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)

Funkce RANK

Funkce RANK se používá k načtení seřazených řádků na základě podmínky klauzule ORDER BY. Pokud například chcete najít název vozu s třetím nejvyšším výkonem, můžete použít funkci RANK.
Podívejme se na funkci RANK v akci:

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

Výše uvedený skript najde a seřadí všechny záznamy v tabulce Cars a seřadí je v sestupném pořadí. Výstup vypadá takto:

Sloupec PowerRank ve výše uvedené tabulce obsahuje RANK vozů seřazených sestupně podle jejich výkonu. Zajímavostí funkce RANK je, že pokud existuje shoda mezi N předchozími záznamy pro hodnotu ve sloupci ORDER BY, funkce RANK přeskočí dalších N-1 pozic před zvýšením počítadla. Například ve výše uvedeném výsledku je shoda hodnot ve sloupci síly mezi 1. a 2. řádkem, proto funkce RANK přeskočí další (2-1 =1) jeden záznam a skočí přímo na 3. řádek.
Funkci RANK lze použít v kombinaci s klauzulí PARTITION BY. V takovém případě bude hodnocení resetováno pro každý nový oddíl. Podívejte se na následující skript:

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

Ve výše uvedeném skriptu rozdělíme výsledky podle sloupce společnosti. Nyní pro každou společnost bude RANK resetován na 1, jak je uvedeno níže:

Funkce DENSE_RANK

Funkce DENSE_RANK je podobná funkci RANK, avšak funkce DENSE_RANK nepřeskočí žádné pořadí, pokud existuje nerozhodný výsledek mezi pořadím předchozích záznamů. Podívejte se na následující skript.

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

Z výstupu můžete vidět, že přestože je mezi pozicemi v prvních dvou řádcích shoda, další pozice není přeskočena a byla jí přiřazena hodnota 2 místo 3. Stejně jako u funkce RANK může klauzule PARTITION BY lze také použít s funkcí DENSE_RANK, jak je znázorněno níže:

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

Funkce ROW_NUMBER

Na rozdíl od funkcí RANK a DENSE_RANK funkce ROW_NUMBER jednoduše vrací číslo řádku seřazených záznamů začínajících 1. Pokud jsou například funkce RANK a DENSE_RANK prvních dvou záznamů ve sloupci ORDER BY stejné, oběma je přiřazena 1 jako jejich RANK a DENSE_RANK. Funkce ROW_NUMBER však těmto řádkům přiřadí hodnoty 1 a 2, aniž by vzala v úvahu skutečnost, že jsou stejně zohledněny. Chcete-li zobrazit funkci ROW_NUMBER v akci, spusťte následující skript.

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

Z výstupu můžete vidět, že funkce ROW_NUMBER jednoduše přiřadí nové číslo řádku každému záznamu bez ohledu na jeho hodnotu.
Klauzuli PARTITION BY lze také použít s funkcí ROW_NUMBER, jak je uvedeno níže:

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

Výstup vypadá takto:

Podobnosti mezi funkcemi RANK, DENSE_RANK a ROW_NUMBER

Funkce RANK, DENSE_RANK a ROW_NUMBER mají následující podobnosti:
1- Všechny vyžadují pořadí podle klauzule.
2- Všechny vrací rostoucí celé číslo se základní hodnotou 1.
3- Při kombinaci s klauzulí PARTITION BY všechny tyto funkce resetují vrácenou celočíselnou hodnotu na 1, jak jsme viděli.
4- Pokud ve sloupci používaném klauzulí ORDER BY nejsou žádné duplicitní hodnoty, funkce vrací stejný výstup.
Pro ilustraci posledního bodu vytvořte novou tabulku Car1 v databázi ShowRoom bez duplicitních hodnot ve sloupci power. Spusťte následující skript:

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

Výstup vypadá takto:

Vidíte, že ve sloupci výkonu, který se používá v klauzuli ORDER BY, nejsou žádné duplicitní hodnoty, takže výstup funkcí RANK, DENSE_RANK a ROW_NUMBER je stejný.

Rozdíl mezi funkcemi RANK, DENSE_RANK a ROW_NUMBER

Jediný rozdíl mezi funkcemi RANK, DENSE_RANK a ROW_NUMBER je, když jsou ve sloupci použitém v klauzuli ORDER BY duplicitní hodnoty.
Pokud se vrátíte zpět do tabulky Cars v databázi ShowRoom, uvidíte, že obsahuje spoustu duplicitní hodnoty. Zkusme najít RANK, DENSE_RANK a ROW_NUMBER tabulky Cars1 seřazené podle síly. Spusťte následující skript:
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

Výstup vypadá takto:

Z výstupu můžete vidět, že funkce RANK přeskočí dalších N-1 pořadí, pokud existuje shoda mezi N předchozími pořadími. Na druhou stranu funkce DENSE_RANK nepřeskakuje pořadí, pokud je mezi pořadím nerozhodný výsledek. A konečně, funkce ROW_NUMBER se nezabývá hodnocením. Jednoduše vrátí číslo řádku seřazených záznamů. I když jsou ve sloupci použitém v klauzuli ORDER BY duplicitní záznamy, funkce ROW_NUMBER nevrátí duplicitní hodnoty. Místo toho se bude nadále zvyšovat bez ohledu na duplicitní hodnoty.

Užitečné odkazy:

Chcete-li se dozvědět více o funkcích ROW_NUMBER(), RANK() a DENSE_RANK(), přečtěte si fantastický článek od Ahmada Yaseena:

Metody hodnocení řádků na serveru SQL:ROW_NUMBER(), RANK(), DENSE_RANK() a NTILE()


  1. co se stane ve fázi adopce, připravte

  2. Extrakce podřetězců MySQL pomocí oddělovače

  3. nvarchar(max) vs NText

  4. SqlParameter neumožňuje Název tabulky - další možnosti bez útoku sql injection?