Renvoyer de manière fiable les N premières lignes
Pourquoi ORDER BY associé à LIMIT peut produire des résultats non déterministes sans critère de départage
Renvoyer de manière fiable les N premières lignes est une leçon SQL Interview Prep gratuite sur CoddyKit. Ceci est la leçon 3 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.
Le bogue caché des requêtes des N premiers
« Donnez-moi les 5 employés les mieux rémunérés » semble simple : ORDER BY salary DESC LIMIT 5. Mais les intervieweurs tendent un piège. Que se passe-t-il si six personnes ont le même salaire à la limite ? Et si de nombreuses lignes sont ex æquo ?
Le problème central est le déterminisme : lorsque la clé de tri comporte des égalités, LIMIT coupe arbitrairement les résultats et les lignes renvoyées peuvent changer d'une exécution à l'autre. Cette leçon rend les requêtes des N premiers fiables.
Pourquoi ORDER BY + LIMIT peut manquer de déterminisme
Considérez des salaires pour lesquels les rangs 4, 5 et 6 sont tous de 50 000. ORDER BY salary DESC LIMIT 5 doit renvoyer exactement 5 lignes ; il conserve donc deux des trois lignes ex æquo et en exclut une, mais le choix des deux n'est pas défini.
Exécutez la requête deux fois, ou après une modification des plans par l'optimiseur, et vous pourriez obtenir des personnes différentes. Ce non-déterminisme est le bogue que les intervieweurs veulent vous voir repérer.
SELECT name, salary
FROM employees
ORDER BY salary DESC
LIMIT 5;Correction 1 : ajouter un critère de départage unique
La correction la plus simple consiste à rendre l'ordre de tri total en ajoutant une colonne unique, généralement la clé primaire. Ainsi, aucune paire de lignes n'a la même clé complète : la coupure devient déterministe et reproductible.
Cette méthode ne change pas les salaires qui apparaissent, mais elle stabilise le choix entre les lignes ex æquo d'une exécution à l'autre.
SELECT id, name, salary
FROM employees
ORDER BY salary DESC, id ASC
LIMIT 5;Correction 2 : inclure toutes les égalités avec WITH TIES
Parfois, l'exigence est « inclure toutes les personnes ex æquo avec la limite », et non renvoyer exactement N lignes. La norme SQL et SQL Server proposent WITH TIES, qui renvoie les lignes supplémentaires correspondant à la valeur de ORDER BY de la dernière ligne.
Si le 5e salaire est partagé par trois personnes, cette méthode renvoie 7 lignes. Notez que WITH TIES nécessite un ORDER BY.
SELECT name, salary
FROM employees
ORDER BY salary DESC
FETCH FIRST 5 ROWS WITH TIES;Clarifiez d'abord l'exigence
Avant de coder, demandez à l'intervieweur : « S'il y a des égalités à la limite, voulez-vous exactement N lignes ou toutes les lignes ex æquo ? » Cette simple question de clarification témoigne d'une bonne expérience.
- Exactement N, de manière stable : ajoutez un critère de départage unique.
- Toutes les lignes ex æquo incluses : utilisez
WITH TIESouRANK. - Valeurs distinctes : utilisez
DENSE_RANK.
L'approche portable avec une fonction de fenêtre
De nombreux moteurs ne proposent pas WITH TIES. Le motif portable et puissant consiste à utiliser une fonction de classement de fenêtre dans une sous-requête ou une CTE, puis à filtrer selon le classement. ROW_NUMBER renvoie exactement N lignes avec une clé de tri déterministe.
Vous devez encapsuler la fonction de fenêtre, car vous ne pouvez pas y faire référence directement dans WHERE.
SELECT name, salary
FROM (
SELECT name, salary,
ROW_NUMBER() OVER (ORDER BY salary DESC, id ASC) AS rn
FROM employees
) ranked
WHERE rn <= 5;Utiliser RANK pour conserver les égalités
Remplacez ROW_NUMBER par RANK lorsque vous souhaitez conserver toutes les lignes ex æquo et accepter des trous dans la numérotation. Si trois lignes sont ex æquo au rang 4, elles obtiennent toutes le rang 4 et le rang suivant est 7.
Le filtrage avec rank <= 5 renvoie alors chaque ligne correspondant aux cinq premières positions salariales, égalités comprises.
SELECT name, salary
FROM (
SELECT name, salary,
RANK() OVER (ORDER BY salary DESC) AS rnk
FROM employees
) ranked
WHERE rnk <= 5;DENSE_RANK pour les N premières valeurs distinctes
« Les 3 niveaux de salaire les plus élevés » (et non les 3 personnes les mieux rémunérées) signifie qu'il faut considérer des valeurs distinctes. DENSE_RANK attribue le même rang aux lignes ex æquo sans sauter de nombres ; ainsi, dense_rnk <= 3 renvoie toutes les personnes dont le salaire fait partie des trois salaires distincts les plus élevés.
Savoir quelle fonction de classement correspond à chaque formulation est un critère classique pour se démarquer.
SELECT name, salary
FROM (
SELECT name, salary,
DENSE_RANK() OVER (ORDER BY salary DESC) AS drnk
FROM employees
) ranked
WHERE drnk <= 3;Cas particulier du premier résultat
Pour obtenir une seule ligne au premier rang, ORDER BY ... LIMIT 1 fonctionne, mais cette méthode reste exposée aux égalités. Si vous voulez chaque ligne qui détient la valeur maximale, comparez-la au maximum d'une sous-requête ou utilisez RANK() = 1.
La forme avec une sous-requête calculant le maximum est claire et fonctionne avec tous les dialectes.
SELECT name, salary
FROM employees
WHERE salary = (SELECT MAX(salary) FROM employees);Comparer les approches
Résumé : quand utiliser chaque outil pour obtenir des N premiers fiables :
LIMIT+ critère de départage unique : exactement N lignes, résultat stable et solution la plus simple.FETCH ... WITH TIES: exactement N lignes plus les égalités à la limite, selon la norme SQL.ROW_NUMBER: exactement N lignes, de manière déterministe et entièrement portable.RANK: les N premières positions en incluant toutes les égalités.DENSE_RANK: les N premières valeurs distinctes.
Aperçu des N premiers par groupe
L'approche par fenêtre se généralise très bien. Ajoutez PARTITION BY pour obtenir les N premiers dans chaque groupe, par exemple les deux personnes les mieux rémunérées de chaque service. Le même filtre rn <= n s'applique après le partitionnement.
Les N premiers par groupe constituent l'un des problèmes d'entretien les plus fréquents dans la pratique, fondé exactement sur le motif que vous venez d'apprendre.
SELECT department, name, salary
FROM (
SELECT department, name, salary,
ROW_NUMBER() OVER (PARTITION BY department
ORDER BY salary DESC, id ASC) AS rn
FROM employees
) ranked
WHERE rn <= 2;Vérification rapide
Associez l'exigence à la fonction appropriée.
Récapitulatif
Pour renvoyer des N premiers de manière fiable :
ORDER BY ... LIMITseul manque de déterminisme lorsque la clé de tri comporte des égalités.- Ajoutez un critère de départage unique pour obtenir un résultat stable avec exactement N lignes.
- Utilisez
WITH TIESouRANKpour conserver les égalités à la limite. - Utilisez
DENSE_RANKpour les N premières valeurs distinctes. - Demandez toujours si l'intervieweur veut exactement N lignes ou toutes les lignes ex æquo.
Questions Fréquemment Posées
La leçon « Renvoyer de manière fiable les N premières lignes » est-elle gratuite ?
Oui — le texte complet de « Renvoyer de manière fiable les N premières lignes » 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 « Renvoyer de manière fiable les N premières lignes » ?
Pourquoi ORDER BY associé à LIMIT peut produire des résultats non déterministes sans critère de départage 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 3 sur 4.
Combien de temps prend la leçon « Renvoyer de manière fiable les N premières lignes » ?
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
- Tri sur plusieurs colonnes et positionnement des NULL
- LIMIT, OFFSET et FETCH FIRST
- Renvoyer de manière fiable les N premières lignes
- Trier avec des expressions et des alias