ROW_NUMBER pour une numérotation unique
Attribuer un numéro de ligne déterministe dans chaque partition
ROW_NUMBER pour une numérotation unique est une leçon SQL Interview Prep gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage SQL Interview Prep, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours SQL Interview Prep comprend 4 leçons au total.
Ce que garantit ROW_NUMBER
ROW_NUMBER() attribue à chaque ligne de sa partition un entier unique et sans trous, en commençant à 1 et en suivant l'ORDER BY de la fenêtre. Deux lignes ne reçoivent jamais le même numéro, même lorsque leurs valeurs de classement sont identiques.
Cette unicité explique précisément pourquoi les recruteurs l'utilisent pour résoudre les problèmes consistant à « sélectionner une ligne par groupe » et les problèmes de déduplication. Les autres fonctions de classement (RANK, DENSE_RANK) ne garantissent pas l'unicité en cas d'égalité.
Requête ROW_NUMBER minimale
La forme la plus simple numérote l'ensemble des résultats selon un ordre choisi. ROW_NUMBER a toujours besoin d'un ORDER BY à l'intérieur de OVER : sans lui, la numérotation serait arbitraire, et la plupart des moteurs la refusent ou émettent un avertissement.
Ici, l'employé recruté le plus récemment est la ligne 1 si vous triez selon la date d'embauche par ordre décroissant.
SELECT
name,
hire_date,
ROW_NUMBER() OVER (ORDER BY hire_date DESC) AS rn
FROM employees;Numéroter les lignes au sein de partitions
Ajoutez PARTITION BY pour numéroter les lignes indépendamment dans chaque groupe. Le compteur revient à 1 pour chaque nouvelle valeur de partition.
Dans l'exemple, chaque département possède sa propre séquence 1, 2, 3, ordonnée selon le salaire. La personne la mieux rémunérée de chaque département porte le numéro 1 — le fondement du modèle de sélection des N premiers éléments par groupe.
SELECT
department,
name,
salary,
ROW_NUMBER() OVER (
PARTITION BY department
ORDER BY salary DESC
) AS dept_rn
FROM employees;ROW_NUMBER et les égalités : il n'y en a pas
Point essentiel en entretien : lorsque deux lignes ont des valeurs de classement égales, ROW_NUMBER leur attribue tout de même des numéros différents. Celle qui reçoit le plus petit numéro est choisie de manière non déterministe, sauf si vous ajoutez une colonne de départage.
RANKattribuerait le même classement aux lignes à égalité.ROW_NUMBERchoisit arbitrairement un ordre entre elles.
Pour obtenir des résultats reproductibles, ajoutez toujours un critère de départage unique à ORDER BY.
SELECT
name,
salary,
ROW_NUMBER() OVER (
ORDER BY salary DESC, employee_id -- employee_id breaks ties deterministically
) AS rn
FROM employees;La règle du critère de départage déterministe
Si votre ORDER BY ne définit pas un ordre strict (aucune combinaison de colonnes n'est unique), la numérotation des lignes peut changer d'une exécution à l'autre, même avec les mêmes données. Les recruteurs placent ce piège dans les questions sur la pagination et les « enregistrements les plus récents ».
Règle générale : ajoutez une clé primaire ou une autre colonne unique comme dernière clé de tri chaque fois que le résultat doit rester stable.
-- Unstable: many rows can share the same created_at
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC)
-- Stable: id guarantees a single deterministic winner
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC, id DESC)Exemple détaillé : dernière commande par client
Une question classique : « Retourner la commande la plus récente de chaque client. » Numérotez les commandes de chaque client par date décroissante, puis conservez rn = 1 dans une requête externe.
Comme ROW_NUMBER garantit exactement une ligne portant le numéro 1 par partition, vous obtenez précisément une ligne par client — aucun doublon, même si deux commandes ont le même horodatage (le critère de départage règle le cas).
SELECT customer_id, order_id, order_date, amount
FROM (
SELECT
customer_id, order_id, order_date, amount,
ROW_NUMBER() OVER (
PARTITION BY customer_id
ORDER BY order_date DESC, order_id DESC
) AS rn
FROM orders
) t
WHERE rn = 1;Exemple détaillé : dédupliquer les lignes
ROW_NUMBER est l'outil de déduplication le plus simple. Partitionnez selon les colonnes qui définissent un doublon, triez selon une règle de préférence, puis conservez rn = 1.
Ici, nous considérons comme des doublons les lignes qui ont la même adresse e-mail et conservons celle qui a été créée en premier. Tout ce qui possède rn > 1 est un doublon que vous pouvez supprimer ou ignorer.
SELECT id, email, created_at
FROM (
SELECT
id, email, created_at,
ROW_NUMBER() OVER (
PARTITION BY email
ORDER BY created_at ASC, id ASC
) AS rn
FROM users
) t
WHERE rn = 1;ROW_NUMBER pour la pagination
Avant que OFFSET/FETCH ne soit généralisé, ROW_NUMBER pilotait la pagination, et c'est encore le cas dans SQL Server et de nombreux traitements ETL. Numérotez les lignes selon un ordre stable, puis filtrez une plage de numéros dans une requête externe.
Attention en entretien : la pagination n'est correcte que si l'ordre est déterministe ; sinon, la même ligne peut apparaître sur deux pages ou être complètement ignorée.
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY created_at, id) AS rn
FROM articles
) t
WHERE rn BETWEEN 21 AND 40; -- page 2, 20 per pageAttribuer une séquence pour réordonner les données
Parfois, vous avez simplement besoin d'un index séquentiel, par exemple pour renuméroter les lignes après un tri, créer une étiquette de 1 à N ou associer des lignes à une série générée. Appliquer ROW_NUMBER à l'ordre souhaité produit une séquence dense et propre, sans trous.
C'est également ainsi que vous donnez une position stable à un ensemble arbitraire et non ordonné afin de pouvoir l'utiliser plus tard dans une jointure.
SELECT
ROW_NUMBER() OVER (ORDER BY score DESC, player_id) AS leaderboard_position,
player_id,
score
FROM scores;ROW_NUMBER ou COUNT pour la « énième ligne »
Si l'on vous demande « la 3e commande la plus récente » ou « la 2e ligne », utilisez ROW_NUMBER et filtrez selon la valeur exacte dans une requête externe. Comme la numérotation est unique, rn = 3 renvoie exactement une ligne.
Comparez avec RANK : si vous voulez la 2e valeur distincte (par exemple, le deuxième salaire le plus élevé en incluant les égalités), ROW_NUMBER n'est pas le bon outil — il faut utiliser DENSE_RANK, présenté dans la prochaine leçon.
SELECT order_id, order_date
FROM (
SELECT order_id, order_date,
ROW_NUMBER() OVER (ORDER BY order_date DESC, order_id DESC) AS rn
FROM orders
) t
WHERE rn = 3; -- exactly the 3rd most recent orderRécapitulatif des pièges
Gardez ces points en tête sous la pression d'un entretien :
ROW_NUMBERest toujours unique et sans trous au sein d'une partition.- Il nécessite un
ORDER BYdansOVER; sans critère de départage unique, les résultats sont non déterministes en cas d'égalité. - Il ne peut pas être filtré dans
WHERE— placez-le dans une sous-requête ou une CTE. - Utilisez-le pour obtenir une ligne par groupe, dédupliquer et paginer ; utilisez
DENSE_RANKlorsque les valeurs à égalité doivent partager un numéro.
Vérification rapide
Comment ROW_NUMBER traite-t-il les lignes à égalité selon la valeur de ORDER BY ?
Récapitulatif : numérotation déterministe
ROW_NUMBER est l'outil à utiliser pour obtenir une numérotation unique et sans trous au sein des partitions. Vous avez appris à :
- Numéroter des ensembles complets et des groupes répartis par partition.
- Ajouter un critère de départage unique pour obtenir des résultats déterministes et reproductibles.
- Résoudre les problèmes de dernière ligne par clé, de déduplication, de pagination et d'én ième ligne en filtrant
rndans une requête externe.
Ensuite, vous verrez comment RANK et DENSE_RANK attribuent délibérément le même numéro aux valeurs à égalité — et en quoi leur gestion des trous diffère.
Questions Fréquemment Posées
La leçon « ROW_NUMBER pour une numérotation unique » est-elle gratuite ?
Oui — le texte complet de « ROW_NUMBER pour une numérotation unique » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours SQL Interview Prep, passe à CoddyKit PRO. Le cours SQL Interview Prep comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « ROW_NUMBER pour une numérotation unique » ?
Attribuer un numéro de ligne déterministe dans chaque partition Tu pratiques SQL Interview Prep avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer SQL Interview Prep ?
Aucune expérience préalable n'est requise. SQL Interview Prep sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.
Combien de temps prend la leçon « ROW_NUMBER pour une numérotation unique » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon SQL Interview Prep ?
Oui. Chaque leçon SQL Interview Prep inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- OVER, PARTITION BY et ORDER BY
- ROW_NUMBER pour une numérotation unique
- RANK ou DENSE_RANK en cas d’égalité
- Filtrer sur un résultat de fenêtre