22nd May 2023 9 minutes de lecture Comment utiliser la fonction SQL RANK OVER (PARTITION BY) Tihomir Babic sql rank Table des matières Qu'est-ce que RANK() ? Que fait RANK() ? Comment RANK() fonctionne avec OVER (ORDER BY) Comment RANK() fonctionne avec OVER (PARTITION BY) Exemple bonus Ajouter RANK() à votre vocabulaire SQL Le classement des données en SQL est un jeu d'enfant si vous savez comment utiliser RANK() pour effectuer un classement sur une partition. Cet article vous montre comment procéder, ainsi que les différences entre RANK() et DENSE_RANK() et ROW_NUMBER(). Si vous travaillez avec SQL dans un cadre professionnel, vous avez dû classer des données au moins une fois. Pensez au classement des mois/années/trimestres en fonction des revenus ou des coûts, des produits les plus vendus, des articles les plus consultés ou des chansons les plus écoutées, des employés en fonction de leur salaire, des branches les plus rentables, et j'en passe. Ou encore à classer les livres en fonction de leurs ventes. Le fait est que vous devez souvent classer des données au sein d'une certaine catégorie, ou partition comme nous l'appelons. C'est là que SQL RANK OVER (PARTITION BY) entre en jeu ! Il s'agit d'un exemple typique des fonctions de fenêtre en SQL. Pour une explication plus détaillée des fonctions de fenêtre, notre cours sur les fonctions de fenêtre est le meilleur. Grâce à 218 exercices interactifs, vous en apprendrez plus sur PARTITION BY et sur d'autres clauses de fonction fenêtre, telles que ORDER BY, ROWS, et RANGE. Ces fonctions sont utilisées non seulement dans le classement, mais aussi dans les fonctions de fenêtre d'agrégation et d'analyse. Revenons aux ventes de livres. Jetez un coup d'œil à ce tableau, dont le code de création se trouve ici. Comment classer les ventes de livres dans chaque langue ? idtitleauthororiginal_languagesalesclassify_under 1The HobbitJ. R. R. TolkienEnglish100Fantasy 2Watership DownRichard AdamsEnglish50Fantasy 3Harry Potter and the Philosopher's StoneJ. K. RowlingEnglish120Fantasy 4The PlagueAlbert CamusFrench12Classics 5The Divine ComedyDante AlighieriItalian12Poetry 6War and PeaceLeo TolstoyRussian36Classics 7Nineteen Eighty-FourGeorge OrwellEnglish30Classics 8Andromeda NebulaIvan YefremovRussian20Science fiction 9The Little PrinceAntoine de Saint-ExupéryFrench200Kids 10The StrangerAlbert CamusFrench10Classics 11The Adventures of PinocchioCarlo CollodiItalian35Kids 12The Name of the RoseUmberto EcoItalian50Classics 13One Hundred Years of SolitudeGabriel García MárquezSpanish50Classics 14Don QuixoteMiguel de CervantesSpanish500Classics 15LolitaVladimir NabokovEnglish50Classics La solution est simple si l'on sait que la langue, dans cet exemple, agit comme une partition de données. SELECT original_language, title, author, sales, RANK() OVER (PARTITION BY original_language ORDER BY sales DESC) AS sales_rank FROM books; Et c'est le cas ici ! original_languagetitleauthorsalessales_rank EnglishHarry Potter and the Philosopher's StoneJ. K. Rowling1201 EnglishThe HobbitJ. R. R. Tolkien1002 EnglishLolitaVladimir Nabokov503 EnglishWatership DownRichard Adams503 EnglishNineteen Eighty-FourGeorge Orwell305 FrenchThe Little PrinceAntoine de Saint-Exupéry2001 FrenchThe PlagueAlbert Camus122 FrenchThe StrangerAlbert Camus103 ItalianThe Name of the RoseUmberto Eco501 ItalianThe Adventures of PinocchioCarlo Collodi352 ItalianThe Divine ComedyDante Alighieri123 RussianWar and PeaceLeo Tolstoy361 RussianAndromeda NebulaIvan Yefremov202 SpanishDon QuixoteMiguel de Cervantes5001 SpanishOne Hundred Years of SolitudeGabriel García Márquez502 Maintenant, décortiquons cet exemple. Qu'est-ce que RANK() ? En termes simples, RANK() est une fonction de fenêtre. Les fonctions de fenêtre SQL sont similaires aux fonctions d'agrégation en ce sens qu'elles s'appliquent à un groupe de lignes. Une grande différence : les fonctions de fenêtre conservent les détails des lignes individuelles, contrairement aux fonctions d'agrégat avec GROUP BY. Que fait RANK() ? Comme son nom l'indique, elle classe les données. Il s'agit donc d'une fonction de fenêtre de classement, au même titre que DENSE_RANK() et ROW_NUMBER(). Lorsque vous utilisez l'une de ces fonctions de fenêtre, elle doit être accompagnée d'une clause OVER (ORDER BY). La clause OVER() est obligatoire pour toute fonction fenêtre. C'est elle qui transforme une fonction "normale" en fonction fenêtre. Pour ces fonctions de classement, le ORDER BY entre parenthèses définit l'ordre dans lequel le classement est effectué. Cet ordre peut être croissant ou décroissant. Gardez à l'esprit que cela n'affecte pas l'ordre des lignes dans le résultat ; cela se fait à l'aide d'un ORDER BY à la fin de la requête. Pour en savoir plus, consultez notre article sur la fonction de fenêtre RANK(). Comment RANK() fonctionne avec OVER (ORDER BY) Reprenons l'ensemble de données ci-dessus. Prenons l'ensemble du tableau et classons les livres en fonction des ventes. Voyons ce qui se passe. SELECT title, author, sales, RANK() OVER (ORDER BY sales DESC) AS sales_rank FROM books; Il s'agit de la même requête que la précédente, sauf que celle-ci ne sélectionne pas la langue et n'utilise pas PARTITION BY. La fonction RANK() est donc suivie de OVER(). La clause ORDER BY indique à la fonction de classer les données par ordre décroissant des ventes, c'est-à-dire des livres les plus vendus aux livres les moins vendus. La clause PARTITION BY étant omise, la fonction classe l'ensemble du tableau. Voici les dix premières lignes du résultat. titleauthorsalessales_rank Don QuixoteMiguel de Cervantes5001 The Little PrinceAntoine de Saint-Exupéry2002 Harry Potter and the Philosopher's StoneJ. K. Rowling1203 The HobbitJ. R. R. Tolkien1004 LolitaVladimir Nabokov505 Watership DownRichard Adams505 The Name of the RoseUmberto Eco505 One Hundred Years of SolitudeGabriel García Márquez505 War and PeaceLeo Tolstoy369 The Adventures of PinocchioCarlo Collodi3510 Ce qu'il faut remarquer ici, c'est qu'il y a quatre livres vendus à 50 millions d'exemplaires, et qu'ils sont tous classés en cinquième position. C'est en cela que RANK() diffère des deux autres fonctions de fenêtre de classement : elle attribue le même rang aux valeurs égales. Lorsque la fonction atteint la valeur de vente suivante (dans ce cas, 36 millions d'exemplaires vendus), elle n'attribue pas la valeur de rang consécutive suivante (6), mais saute pour tenir compte du nombre de valeurs de vente ex æquo. Comme indiqué, le rang "5" apparaît quatre fois ; le rang suivant est donc neuf. DENSE_RANK() classe également les ex æquo avec le même classement. Cependant, contrairement à RANK(), il ne saute pas les valeurs de classement basées sur les égalités. Les mêmes données classées avec DENSE_RANK() se présentent comme suit. titleauthorsalessales_rank Don QuixoteMiguel de Cervantes5001 The Little PrinceAntoine de Saint-Exupéry2002 Harry Potter and the Philosopher's StoneJ. K. Rowling1203 The HobbitJ. R. R. Tolkien1004 LolitaVladimir Nabokov505 Watership DownRichard Adams505 The Name of the RoseUmberto Eco505 One Hundred Years of SolitudeGabriel García Márquez505 War and PeaceLeo Tolstoy366 The Adventures of PinocchioCarlo Collodi357 Après plusieurs livres classés cinquièmes, le rang suivant est le sixième, et non le neuvième comme pour RANK(). Qu'en est-il de ROW_NUMBER()? Il ne se préoccupe pas des ex aequo ou des sauts. Il se contente de classer les lignes de manière séquentielle. Les dix premiers rangs obtenus à l'aide de ROW_NUMBER() sont présentés ci-dessous. titleauthorsalessales_rank Don QuixoteMiguel de Cervantes5001 The Little PrinceAntoine de Saint-Exupéry2002 Harry Potter and the Philosopher's StoneJ. K. Rowling1203 The HobbitJ. R. R. Tolkien1004 LolitaVladimir Nabokov505 Watership DownRichard Adams506 The Name of the RoseUmberto Eco507 One Hundred Years of SolitudeGabriel García Márquez508 War and PeaceLeo Tolstoy369 The Adventures of PinocchioCarlo Collodi3510 Les différences entre ces fonctions sont expliquées dans l'aperçu des fonctions de classement. Comment RANK() fonctionne avec OVER (PARTITION BY) La clause PARTITION BY divise les données en partitions ou sous-ensembles. Lorsqu'elle est utilisée avec RANK(), cela signifie que les données sont classées à l'intérieur de la partition. Lorsqu'elles atteignent la deuxième partition, le classement est réinitialisé à partir de la première. Reprenons la requête du début de cet article pour clarifier ce point. SELECT original_language, title, author, sales, RANK() OVER (PARTITION BY original_language ORDER BY sales DESC) AS sales_rank FROM books; Dans cette requête, RANK() est utilisé avec PARTITION BY. La partition, dans ce cas, est original_language. Le classement est effectué par ordre décroissant des ventes, comme spécifié dans la clause ORDER BY. La façon dont nous avons écrit PARTITION BY et ORDER BY signifie que les livres sont classés en fonction des ventes, mais dans chaque catégorie linguistique. Une fois que la fonction a classé tous les livres d'une langue, elle recommence lorsqu'elle atteint la deuxième langue, et ainsi de suite. C'est ce que nous voyons dans le résultat de la requête. original_languagetitleauthorsalessales_rank EnglishHarry Potter and the Philosopher's StoneJ. K. Rowling1201 EnglishThe HobbitJ. R. R. Tolkien1002 EnglishLolitaVladimir Nabokov503 EnglishWatership DownRichard Adams503 EnglishNineteen Eighty-FourGeorge Orwell305 FrenchThe Little PrinceAntoine de Saint-Exupéry2001 FrenchThe PlagueAlbert Camus122 FrenchThe StrangerAlbert Camus103 ItalianThe Name of the RoseUmberto Eco501 ItalianThe Adventures of PinocchioCarlo Collodi352 ItalianThe Divine ComedyDante Alighieri123 RussianWar and PeaceLeo Tolstoy361 RussianAndromeda NebulaIvan Yefremov202 SpanishDon QuixoteMiguel de Cervantes5001 SpanishOne Hundred Years of SolitudeGabriel García Márquez502 Nous avons marqué chaque partition d'une couleur différente pour faciliter la visualisation des différentes partitions. Le livre le plus vendu en anglais est Harry Potter et l'école des sorciers de J.K. Rowling. Vient ensuite Le Hobbit. Lolita et Watership Down sont tous deux classés en troisième position, car RANK() attribue le même rang aux livres ayant la même valeur de vente. Ensuite, on saute une valeur de rang, et Nineteen Eighty-Four est classé cinquième. La partition suivante est la langue française, et le classement recommence. Le Petit Prince est le livre le plus vendu en français. La même logique s'applique aux livres en italien, en russe et en espagnol. Exemple bonus Nous avons étudié ces requêtes pour montrer comment fonctionne RANK() OVER (PARTITION BY). Maintenant, mettons-nous à l'œuvre ! L'exemple suivant n'est pas très différent de la première requête. Vous ne devriez pas avoir de difficultés à appliquer ce que vous avez appris. La table books nommée classify_under. Elle indique la catégorie dans laquelle chaque livre doit être placé dans la librairie. Classons les livres par ventes pour chaque catégorie. SELECT classify_under, title, author, sales, RANK() OVER (PARTITION BY classify_under ORDER BY sales DESC) AS sales_rank FROM books; La requête sélectionne la colonne classify_under au lieu de original_language dans la première requête. Toutes les autres colonnes sélectionnées sont identiques. Il y a également une différence dans RANK(). Puisque nous établissons un classement par classify_under, c'est cette colonne qui doit figurer dans la clause PARTITION BY. Une fois de plus, nous voulons classer les livres par ventes dans l'ordre décroissant. Voici le classement : classify_undertitleauthorsalessales_rank ClassicsDon QuixoteMiguel de Cervantes5001 ClassicsLolitaVladimir Nabokov502 ClassicsThe Name of the RoseUmberto Eco502 ClassicsOne Hundred Years of SolitudeGabriel García Márquez502 ClassicsWar and PeaceLeo Tolstoy365 ClassicsNineteen Eighty-FourGeorge Orwell306 ClassicsThe PlagueAlbert Camus127 ClassicsThe StrangerAlbert Camus108 FantasyHarry Potter and the Philosopher's StoneJ. K. Rowling1201 FantasyThe HobbitJ. R. R. Tolkien1002 FantasyWatership DownRichard Adams503 KidsThe Little PrinceAntoine de Saint-Exupéry2001 KidsThe Adventures of PinocchioCarlo Collodi352 PoetryThe Divine ComedyDante Alighieri121 Science fictionAndromeda NebulaIvan Yefremov201 Par pure coïncidence, il y a à nouveau cinq partitions. Dans la catégorie "Classiques", Don Quichotte est le livre le plus vendu. Ensuite, il y a trois livres classés en deuxième position. La séquence de classement est sautée jusqu'à ce que nous arrivions à Guerre et Paix, à la cinquième place. Les autres classiques sont classés dans l'ordre puisqu'il n'y a plus d'égalité. Dans les autres catégories, il n'y a pas d'ex æquo : les catégories "poésie" et "science-fiction" ne comptent qu'un seul livre chacune. Il n'y a donc que le premier rang. Pour plus d'exemples avec d'autres fonctions de fenêtre, consultez notre article expliquant comment utiliser PARTITION BY. Ajouter RANK() à votre vocabulaire SQL Nous avons vu les utilisations les plus typiques de la fonction de fenêtre RANK(). Bien qu'elle nécessite une clause OVER (ORDER BY), la clause PARTITION BY débloque ses possibilités. Elle fait de RANK() un outil sophistiqué pour classer les données dans une ou plusieurs partitions avec facilité dans votre travail quotidien. Pour en savoir plus sur RANK() et d'autres fonctions de fenêtre (de classement) et les mettre en pratique, utilisez notre cours Fonctions de fenêtrage cours. Vous obtiendrez une explication encore plus détaillée du classement et aurez l'occasion d'écrire beaucoup de code dans nos exercices. Bon classement ! Tags: sql rank