You are on page 1of 11

Fonctions de classement (Transact-SQL)

Les fonctions de classement renvoient une valeur de classement pour chaque ligne d'une
partition. Selon la fonction utilise, certaines lignes peuvent recevoir la mme valeur que
d'autres lignes. Les fonctions de classement sont non dterministes.
Transact-SQL offre les fonctions de classement suivantes :

RANK NTILE
DENSE_RANK ROW_NUMBER
Exemples

Dans l'exemple suivant, les quatre fonctions de classement sont utilises dans la mme
requte. Reportez-vous aux rubriques consacres chacune d'entre elles pour consulter des
exemples plus spcifiques.

USE AdventureWorks2012 ;
GO
SELECT p.FirstName, p.LastName
, ROW_NUMBER () OVER (ORDER BY a.PostalCode) AS "Row Number"
, RANK () OVER (ORDER BY a.PostalCode) AS Rank
, DENSE_RANK () OVER (ORDER BY a.PostalCode) AS "Dense Rank"
, NTILE(4) OVER (ORDER BY a.PostalCode) AS Quartile
, s.SalesYTD
, a.PostalCode
FROM Sales.SalesPerson AS s
INNER JOIN Person.Person AS p
ON s.BusinessEntityID = p.BusinessEntityID
INNER JOIN Person.Address AS a
ON a.AddressID = p.BusinessEntityID
WHERE TerritoryID IS NOT NULL AND SalesYTD <> 0;

Voici l'ensemble des rsultats.


Row Dense
FirstName LastName Rank Quartile SalesYTD PostalCode
Number Rank
Michael Blythe 1 1 1 1 4557045.0459 98027
Linda Mitchell 2 1 1 1 5200475.2313 98027
Jillian Carson 3 1 1 1 3857163.6332 98027
Garrett Vargas 4 1 1 1 1764938.9859 98027
Tsvi Reiter 5 1 1 2 2811012.7151 98027
Shu Ito 6 6 2 2 3018725.4858 98055
Jos Saraiva 7 6 2 2 3189356.2465 98055
David Campbell 8 6 2 3 3587378.4257 98055
Tete Mensa-Annan 9 6 2 3 1931620.1835 98055
Lynn Tsoflias 10 6 2 3 1758385.926 98055
Rachel Valdez 11 6 2 4 2241204.0424 98055
Jae Pak 12 6 2 4 5015682.3752 98055
Ranjit Varkey 13 6 2 4 3827950.238 98055
Chudukatil

1
ROW_NUMBER (Transact-SQL)

SQL Server ( partir de la version 2008)

Retourne le numro squentiel d'une ligne d'une partition d'un jeu de rsultats, en
commenant 1 pour la premire ligne de chaque partition.

Syntaxe

ROW_NUMBER ( )
OVER ([PARTITION BY value_expression, ... [n]] order_by_clause)

Arguments

PARTITION BY value_expression
Divise le jeu de rsultats gnr par la clause FROM en partitions auxquelles la fonction
ROW_NUMBER est applique. value_expression spcifie la colonne par laquelle le jeu de
rsultats est partitionn. Si PARTITION BY n'est pas spcifi, la fonction gre toutes les
lignes du jeu de rsultats de la requte en un seul groupe. Pour plus d'informations, consultez
Clause OVER (Transact-SQL).

order_by_clause
La clause ORDER BY dtermine la squence dans laquelle les lignes d'une partition
spcifique reoivent leur valeur ROW_NUMBER unique. Elle est obligatoire. Pour plus
d'informations, consultez Clause OVER (Transact-SQL).

Types de retour bigint

Remarques d'ordre gnral

Rien ne garantit que les lignes retournes par une requte utilisant ROW_NUMBER () seront
ordonnes exactement de la mme manire chaque excution, sauf si les conditions
suivantes sont vrifies.

Les valeurs de la colonne partitionne sont uniques.

Les valeurs des colonnes ORDER BY sont uniques.

Les combinaisons de valeurs de la colonne de partition et des colonnes ORDER BY sont


uniques.

ROW_NUMBER () n'est pas dterministe. Pour plus d'informations, consultez Fonctions


dterministes et non dterministes.

2
Exemples

A. Retour du nombre de lignes pour les vendeurs

L'exemple suivant calcule un numro de ligne pour les vendeurs de Adventure Works Cycles
en fonction de leur classement de ventes de l'anne.

USE AdventureWorks2012;
GO
SELECT ROW_NUMBER () OVER (ORDER BY SalesYTD DESC) AS Row,
FirstName, LastName, ROUND (SalesYTD, 2,1) AS "Sales YTD"
FROM Sales.vSalesPerson
WHERE TerritoryName IS NOT NULL AND SalesYTD <> 0;

Voici l'ensemble des rsultats.

Row FirstName LastName SalesYTD


--- ----------- ---------------------- -----------------
1 Linda Mitchell 4251368.54
2 Jae Pak 4116871.22
3 Michael Blythe 3763178.17
4 Jillian Carson 3189418.36
5 Ranjit Varkey Chudukatil 3121616.32
6 Jos Saraiva 2604540.71
7 Shu Ito 2458535.61
8 Tsvi Reiter 2315185.61
9 Rachel Valdez 1827066.71
10 Tete Mensa-Annan 1576562.19
11 David Campbell 1573012.93
12 Garrett Vargas 1453719.46
13 Lynn Tsoflias 1421810.92
14 Pamela Ansman-Wolfe 1352577.13

B. Retour d'un sous-ensemble de lignes

L'exemple suivant calcule les numros de ligne pour toutes les lignes de la table de
SalesOrderHeader dans l'ordre d'OrderDate et retourne uniquement les lignes 50 60
inclus.

USE AdventureWorks2012;
GO
WITH OrderedOrders AS
(
SELECT SalesOrderID, OrderDate,
ROW_NUMBER () OVER (ORDER BY OrderDate) AS RowNumber
FROM Sales.SalesOrderHeader
)
SELECT SalesOrderID, OrderDate, RowNumber
FROM OrderedOrders
WHERE RowNumber BETWEEN 50 AND 60;

3
C. Utilisation de Using ROW_NUMBER () avec PARTITION

L'exemple suivant utilise l'argument PARTITION BY pour partitionner le jeu de rsultats d'une
requte par la colonne TerritoryName. La clause ORDER BY spcifie dans la clause OVER
classe les lignes de chaque partition par la colonne SalesYTD. La clause ORDER BY dans
l'instruction SELECT dtermine l'ordre du jeu de rsultats de la requte entier par

TerritoryName.

USE AdventureWorks2012;
GO
SELECT FirstName, LastName, TerritoryName, ROUND (SalesYTD, 2,1),
ROW_NUMBER () OVER (PARTITION BY TerritoryName ORDER BY SalesYTD DESC) AS
Row
FROM Sales.vSalesPerson
WHERE TerritoryName IS NOT NULL AND SalesYTD <> 0
ORDER BY TerritoryName;

Voici l'ensemble des rsultats.


FirstName LastName TerritoryName SalesYTD Row
--------- -------------------- ------------------ ------------ ---
Lynn Tsoflias Australia 1421810.92 1
Jos Saraiva Canada 2604540.71 1
Garrett Vargas Canada 1453719.46 2
Jillian Carson Central 3189418.36 1
Ranjit Varkey Chudukatil France 3121616.32 1
Rachel Valdez Germany 1827066.71 1
Michael Blythe Northeast 3763178.17 1
Tete Mensa-Annan Northwest 1576562.19 1
David Campbell Northwest 1573012.93 2
Pamela Ansman-Wolfe Northwest 1352577.13 3
Tsvi Reiter Southeast 2315185.61 1
Linda Mitchell Southwest 4251368.54 1
Shu Ito Southwest 2458535.61 2
Jae Pak United Kingdom 4116871.22 1

RANK (Transact-SQL)

**CETTE RUBRIQUE SAPPLIQUE : ** ! [](../Image/Applies%20to/yes.png)SQL


Server \( partir de la version 2008\) !
[](../Image/Applies%20to/yes.png)Azure SQL Database !
[](../Image/Applies%20to/yes.png)Azure SQL Data Warehouse !
[](../Image/Applies%20to/yes.png)Parallel Data Warehouse

Retourne le rang de chaque ligne au sein de la partition d'un jeu de rsultats. Le rang d'une
ligne est un, plus le nombre de rangs prcdant la ligne en question.

Syntaxe

RANK ( ) OVER ([partition_by_clause] order_by_clause)

4
Arguments

OVER ([partition_by_clause] order_by_clause)


partition_by_clause divise le jeu de rsultats gnr par la clause FROM en partitions
auxquelles la fonction est applique. S'il n'est pas spcifi, la fonction gre toutes les lignes du
jeu de rsultats de la requte en un seul groupe. order_by_clause dtermine l'ordre des
donnes avant que la fonction soit applique. L'attribut order_by_clause est requis. Les
<lignes ou la clause de la plage> de la clause OVER ne peuvent pas tre spcifies pour la
fonction RANK. Pour plus d'informations, consultez Clause OVER (Transact-SQL).

Types de retour bigint

Notes

Si au moins deux lignes sont lies pour un rang, chacune d'entre elles reoit le mme rang. Par
exemple, si les deux meilleurs vendeurs ont la mme valeur SalesYTD, leur rang tous deux
est un. Le rang du vendeur qui suit dans la hirarchie SalesYTD est trois, car il existe deux
lignes au rang suprieur. Par consquent, la fonction RANK ne retourne pas toujours des
entiers conscutifs.

L'ordre de tri utilis pour toute la requte dtermine l'ordre d'apparition des lignes dans un jeu
de rsultats.

RANK n'est pas dterministe. Pour plus d'informations, consultez Fonctions dterministes et
non dterministes.

Exemples

A. Classement des lignes d'une partition

L'exemple suivant classe les produits d'inventaire aux emplacements d'inventaire suivants en
fonction de leurs quantits. Le jeu de rsultats est partitionn par LocationID et class
logiquement par Quantity. Notez que les produits 494 et 495 ont la mme quantit. tant
lis, ils sont tous deux classs numro un.

USE AdventureWorks2012;
GO
SELECT i.ProductID, p.Name, i.LocationID, i.Quantity
, RANK () OVER
(PARTITION BY i.LocationID ORDER BY i.Quantity DESC) AS Rank
FROM Production.ProductInventory AS i
INNER JOIN Production.Product AS p
ON i.ProductID = p.ProductID
WHERE i.LocationID BETWEEN 3 AND 4
ORDER BY i.LocationID;
GO

5
Voici l'ensemble des rsultats.

ProductID Name LocationID Quantity Rank


----------- ---------------------- ------------ -------- ----
494 Paint - Silver 3 49 1
495 Paint - Blue 3 49 1
493 Paint - Red 3 41 3
496 Paint - Yellow 3 30 4
492 Paint - Black 3 17 5
495 Paint - Blue 4 35 1
496 Paint - Yellow 4 25 2
493 Paint - Red 4 24 3
492 Paint - Black 4 14 4
494 Paint - Silver 4 12 5

B. Classement de toutes les lignes dans un jeu de rsultats

L'exemple suivant retourne les dix principaux employs classs en fonction de leur salaire.
tant donn qu'aucune clause PARTITION BY n'a t spcifie, la fonction RANK a t
applique toutes les lignes du jeu de rsultats.

USE AdventureWorks2012
SELECT TOP(10) BusinessEntityID, Rate,
RANK () OVER (ORDER BY Rate DESC) AS RankBySalary
FROM HumanResources.EmployeePayHistory AS eph1
WHERE RateChangeDate = (SELECT MAX(RateChangeDate)
FROM HumanResources.EmployeePayHistory AS eph2
WHERE eph1.BusinessEntityID =
eph2.BusinessEntityID)
ORDER BY BusinessEntityID;

Voici l'ensemble des rsultats.

BusinessEntityID Rate RankBySalary


---------------- --------------------- --------------------
1 125.50 1
2 63.4615 4
3 43.2692 8
4 29.8462 19
5 32.6923 16
6 32.6923 16
7 50.4808 6
8 40.8654 10
9 40.8654 10
10 42.4808 9
DENSE_RANK (Transact-SQL)
**CETTE RUBRIQUE SAPPLIQUE : ** ! [](../Image/Applies%20to/yes.png)SQL
Server \( partir de la version 2008\) !
[](../Image/Applies%20to/yes.png)Azure SQL Database !
[](../Image/Applies%20to/yes.png)Azure SQL Data Warehouse !
[](../Image/Applies%20to/yes.png)Parallel Data Warehouse

6
Retourne le rang des lignes l'intrieur de la partition d'un jeu de rsultats, sans aucun vide
dans le classement. Le rang d'une ligne est gal un plus le nombre de rangs distincts
prcdant la ligne en question.

Syntaxe
DENSE_RANK ( ) OVER ([<partition_by_clause>] < order_by_clause >)
Arguments
<partition_by_clause>
Divise le jeu de rsultats gnr par la clause FROM en partitions auxquelles la fonction
DENSE_RANK est applique. Pour connatre la syntaxe de PARTITION BY, consultez
Clause OVER (Transact-SQL).

<order_by_clause>
Dtermine l'ordre dans lequel la fonction DENSE_RANK est applique aux lignes dans une
partition.

Types de retour bigint

Notes

Si au moins deux lignes sont lies un rang de la mme partition, elles reoivent le mme
rang. Par exemple, si les deux meilleurs vendeurs ont la mme valeur SalesYTD, leur rang
tous deux est un. Le commercial dont la valeur SalesYTD est immdiatement infrieure reoit
le rang deux. Cela correspond un rang de plus que le nombre de lignes distinctes prcdant
cette ligne. Par consquent, les nombres retourns par la fonction DENSE_RANK ne
comportent pas de vides et dfinissent toujours des rangs conscutifs.

L'ordre de tri utilis pour l'ensemble de la requte dtermine l'ordre d'apparition des lignes
dans un rsultat. Cela implique qu'une ligne ayant le rang numro un n'est pas ncessairement
la premire ligne de la partition.

DENSE_RANK n'est pas dterministe. Pour plus d'informations, consultez Fonctions


dterministes et non dterministes.

Exemples

A. Classement des lignes d'une partition

L'exemple suivant classe les produits d'inventaire aux emplacements d'inventaire suivants en
fonction de leurs quantits. Le jeu de rsultats est partitionn par LocationID et class
logiquement par Quantity. Notez que les produits 494 et 495 ont la mme quantit. tant
lis, ils sont tous deux classs numro un.

USE AdventureWorks2012;
GO
SELECT i.ProductID, p.Name, i.LocationID, i.Quantity
, DENSE_RANK () OVER
(PARTITION BY i.LocationID ORDER BY i.Quantity DESC) AS Rank
FROM Production.ProductInventory AS i
INNER JOIN Production.Product AS p

7
ON i.ProductID = p.ProductID
WHERE i.LocationID BETWEEN 3 AND 4
ORDER BY i.LocationID;
GO

Voici l'ensemble des rsultats.

ProductID Name LocationID Quantity Rank


----------- ---------------------------------- ---------- -------- -----
494 Paint - Silver 3 49 1
495 Paint - Blue 3 49 1
493 Paint - Red 3 41 2
496 Paint - Yellow 3 30 3
492 Paint - Black 3 17 4
495 Paint - Blue 4 35 1
496 Paint - Yellow 4 25 2
493 Paint - Red 4 24 3
492 Paint - Black 4 14 4
494 Paint - Silver 4 12 5
B. Classement de toutes les lignes dans un jeu de rsultats

L'exemple suivant retourne les dix principaux employs classs en fonction de leur salaire.
tant donn qu'aucune clause PARTITION BY n'a t spcifie, la fonction DENSE_RANK
a t applique toutes les lignes du jeu de rsultats.

USE AdventureWorks2012;
GO
SELECT TOP(10) BusinessEntityID, Rate,
DENSE_RANK () OVER (ORDER BY Rate DESC) AS RankBySalary
FROM HumanResources.EmployeePayHistory;

Voici l'ensemble des rsultats.

BusinessEntityID Rate RankBySalary


---------------- --------------------- --------------------
1 125.50 1
25 84.1346 2
273 72.1154 3
2 63.4615 4
234 60.0962 5
263 50.4808 6
7 50.4808 6
234 48.5577 7
285 48.101 8
274 48.101 8

NTILE (Transact-SQL)
**CETTE RUBRIQUE SAPPLIQUE :** ![](../Image/Applies%20to/yes.png)SQL
Server \( partir de la version 2008\) !
[](../Image/Applies%20to/yes.png)Azure SQL Database !
[](../Image/Applies%20to/yes.png)Azure SQL Data Warehouse !
[](../Image/Applies%20to/yes.png)Parallel Data Warehouse

8
Distribue les lignes d'une partition trie dans un nombre spcifi de groupes. Les groupes sont
numrots partir de un. Pour chaque ligne, NTILE retourne le numro du groupe auquel la
ligne appartient.

Syntaxe

NTILE (integer_expression) OVER ([<partition_by_clause>] < order_by_clause >)

Arguments

integer_expression
Expression constante dont la valeur est un entier positif qui spcifie le nombre de groupes
utiliss pour diviser chaque partition. integer_expression peut tre de type int ou bigint.

<partition_by_clause>
Divise le jeu de rsultats gnr par la clause FROM en partitions auxquelles la fonction est
applique. Pour connatre la syntaxe de PARTITION BY, consultez Clause OVER (Transact-
SQL).

<order_by_clause>
Dtermine l'ordre dans lequel les valeurs de NTILE sont assignes aux lignes d'une partition.
Un entier ne peut pas reprsenter une colonne lorsque <order_by_clause> est utilis dans une
fonction de classement.

Types de retour bigint

Notes

Si le nombre de lignes d'une partition n'est pas divisible par integer_expression, vous
obtiendrez des groupes de deux tailles diffrentes qui diffrent d'un membre. Les groupes plus
grands viennent avant les groupes plus petits dans l'ordre spcifi par la clause OVER. Par
exemple, si le nombre total de lignes est gal 53 et qu'il existe 5 groupes, les trois premiers
groupes contiendront 11 lignes et les deux derniers, 10 lignes. En revanche, si le nombre total
de lignes est divisible par le nombre de groupes, les lignes seront rparties quitablement
entre les diffrents groupes. Par exemple, si le nombre total de lignes est gal 50 et qu'il
existe 5 groupes, chaque compartiment contiendra 10 lignes.

NTILE n'est pas dterministe. Pour plus d'informations, consultez Fonctions dterministes et
non dterministes.

Exemples

A. Division des lignes en groupes

L'exemple suivant divise les lignes en quatre groupes d'employs en fonction de leurs ventes
de l'anne. Dans la mesure o le nombre total de lignes n'est pas divisible par le nombre de
groupes, les deux premiers groupes contiennent quatre lignes tandis que les autres en
possdent trois chacun.

9
USE AdventureWorks2012;
GO
SELECT p.FirstName, p.LastName
, NTILE(4) OVER (ORDER BY SalesYTD DESC) AS Quartile
, CONVERT (nvarchar(20), s.SalesYTD, 1) AS SalesYTD
, a.PostalCode
FROM Sales.SalesPerson AS s
INNER JOIN Person.Person AS p
ON s.BusinessEntityID = p.BusinessEntityID
INNER JOIN Person.Address AS a
ON a.AddressID = p.BusinessEntityID
WHERE TerritoryID IS NOT NULL
AND SalesYTD <> 0;
GO

Voici l'ensemble des rsultats.

FirstName LastName Quartile SalesYTD PostalCode


------------- --------------------- --------- -------------- ----------
Linda Mitchell 1 4, 251,368.55 98027
Jae Pak 1 4, 116,871.23 98055
Michael Blythe 1 3, 763,178.18 98027
Jillian Carson 1 3, 189,418.37 98027
Ranjit Varkey Chudukatil 2 3, 121,616.32 98055
Jos Saraiva 2 2, 604,540.72 98055
Shu Ito 2 2, 458,535.62 98055
Tsvi Reiter 2 2, 315,185.61 98027
Rachel Valdez 3 1, 827,066.71 98055
Tete Mensa-Annan 3 1, 576,562.20 98055
David Campbell 3 1, 573,012.94 98055
Garrett Vargas 4 1, 453,719.47 98027
Lynn Tsoflias 4 1, 421,810.92 98055
Pamela Ansman-Wolfe 4 1, 352,577.13 98027
(14 row(s) affected)

B. Division du jeu de rsultats l'aide de PARTITION BY

L'exemple suivant ajoute l'argument PARTITION BY au code de l'exemple A. Les lignes sont
d'abord partitionnes par PostalCode, puis divises en quatre groupes dans chaque
PostalCode. L'exemple dclare galement une variable @NTILE_Var et utilise cette variable
pour spcifier la valeur du paramtre integer_expression.

USE AdventureWorks2012 ;
GO
DECLARE @NTILE_Var int = 4;

SELECT p.FirstName, p.LastName


, NTILE(@NTILE_Var) OVER (PARTITION BY PostalCode ORDER BY SalesYTD
DESC) AS Quartile
, CONVERT (nvarchar(20), s.SalesYTD, 1) AS SalesYTD
, a.PostalCode
FROM Sales.SalesPerson AS s
INNER JOIN Person.Person AS p

10
ON s.BusinessEntityID = p.BusinessEntityID
INNER JOIN Person.Address AS a
ON a.AddressID = p.BusinessEntityID
WHERE TerritoryID IS NOT NULL
AND SalesYTD <> 0;
GO

Voici l'ensemble des rsultats.


FirstName LastName Quartile SalesYTD PostalCode

------------ -------------------- -------- ------------ ----------


Linda Mitchell 1 4, 251,368.55 98027
Michael Blythe 1 3, 763,178.18 98027
Jillian Carson 2 3, 189,418.37 98027
Tsvi Reiter 2 2, 315,185.61 98027
Garrett Vargas 3 1, 453,719.47 98027
Pamela Ansman-Wolfe 4 1, 352,577.13 98027
Jae Pak 1 4, 116,871.23 98055
Ranjit Varkey Chudukatil 1 3, 121,616.32 98055
Jos Saraiva 2 2, 604,540.72 98055
Shu Ito 2 2, 458,535.62 98055
Rachel Valdez 3 1, 827,066.71 98055
Tete Mensa-Annan 3 1, 576,562.20 98055
David Campbell 4 1, 573,012.94 98055
Lynn Tsoflias 4 1, 421,810.92 98055

11