Renvoyer NULL lorsqu’il n’existe aucune n-ième valeur
Le cas particulier apprécié des recruteurs : gérer élégamment un nombre insuffisant de lignes
Renvoyer NULL lorsqu’il n’existe aucune n-ième valeur est une leçon Coding Interview Prep gratuite sur CoddyKit. Ceci est la leçon 4 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 Coding Interview Prep, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Coding Interview Prep comprend 4 leçons au total.
Le cas limite que les intervieweurs adorent
Après avoir réussi la requête de la Nᵉ valeur la plus élevée, l'intervieweur ajoute : « Et si la table contient moins de N salaires distincts ? Je veux un seul NULL, pas un résultat vide. »
C'est la question qui distingue les candidats ayant mémorisé une requête de ceux qui comprennent le comportement des ensembles de résultats. De nombreuses solutions renvoient silencieusement zéro ligne au lieu d'une ligne contenant NULL.
Cette leçon porte entièrement sur le fait de forcer la production d'exactement une ligne de sortie, dont la valeur est NULL lorsqu'aucune Nᵉ valeur n'existe.
Pourquoi DENSE_RANK seul ne renvoie aucune ligne
Rappelez-vous la requête standard de la Nᵉ valeur la plus élevée. S'il n'existe que deux salaires distincts et que vous demandez le troisième, WHERE rnk = 3 ne correspond à rien, la requête renvoie donc un ensemble vide : zéro ligne.
Un ensemble vide n'est pas équivalent à une ligne contenant NULL. Si la spécification indique « renvoyer NULL », l'ensemble vide échoue à la vérification, même si la logique sous-jacente est correcte.
SELECT salary
FROM (
SELECT salary,
DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
FROM employee
) t
WHERE rnk = 3; -- returns NO rows if fewer than 3 distinct salariesCorrectif 1 : encapsuler dans un SELECT externe
La solution fiable la plus simple consiste à placer toute la requête de la Nᵉ valeur la plus élevée dans une sous-requête scalaire à l'intérieur d'un unique SELECT. Une sous-requête scalaire qui ne trouve aucune ligne s'évalue à NULL, et le SELECT externe produit toujours exactement une ligne.
C'est la réponse canonique à la variante de type LeetCode « renvoyer NULL », et elle fonctionne dans tous les dialectes.
SELECT (
SELECT DISTINCT salary
FROM employee
ORDER BY salary DESC
LIMIT 1 OFFSET 2 -- N = 3
) AS third_highest;Pourquoi l'astuce de la sous-requête scalaire fonctionne
Deux règles se combinent pour produire le comportement souhaité :
- Une sous-requête scalaire doit renvoyer au plus une valeur. Si elle ne renvoie aucune ligne, SQL lui substitue
NULL. - Le SELECT externe sans
FROM(ou avec une source d'une seule ligne) émet toujours exactement une ligne.
Ainsi, lorsque la requête interne trouve la Nᵉ valeur, vous l'obtenez ; lorsqu'elle ne trouve rien, vous obtenez une ligne contenant NULL. C'est exactement le contrat énoncé par l'intervieweur.
Correctif 1 avec la version DENSE_RANK
Le même encadrement fonctionne autour de la solution utilisant une fonction de fenêtre. Placez la requête classée dans la sous-requête scalaire ; si aucune ligne n'a le rang N, la sous-requête renvoie NULL et le SELECT externe renvoie tout de même une ligne.
SELECT (
SELECT salary
FROM (
SELECT salary,
DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
FROM employee
) t
WHERE rnk = 3
) AS third_highest;Correctif 2 : MAX renvoie NULL automatiquement
Rappelez-vous l'approche MAX sous MAX de la leçon 1. Un agrégat sur zéro ligne renvoie NULL et produit tout de même une ligne. Pour la deuxième valeur la plus élevée, c'est une solution concise qui respecte déjà l'exigence NULL.
Limite : étendre l'imbrication de MAX seul à une valeur N arbitraire devient peu élégant ; cette solution convient donc surtout au cas de la deuxième valeur la plus élevée.
SELECT MAX(salary) AS second_highest
FROM employee
WHERE salary < (SELECT MAX(salary) FROM employee);Correctif 3 : COALESCE avec une valeur de remplacement
Si votre environnement garantit une ligne mais que la valeur peut manquer pour une autre raison, vous pouvez entourer le résultat de COALESCE pour fournir une valeur par défaut explicite.
Remarque : COALESCE n'est utile qu'une fois qu'une ligne existe. Il ne transforme pas un ensemble de résultats vide en ligne. Combinez-le donc avec l'encadrement par sous-requête scalaire (qui garantit une ligne), puis appliquez COALESCE à la valeur si vous voulez autre chose que NULL, par exemple 0.
SELECT COALESCE((
SELECT DISTINCT salary
FROM employee
ORDER BY salary DESC
LIMIT 1 OFFSET 2
), 0) AS third_highest_or_zero;Ce qui ne corrige pas le problème
Méfiez-vous des correctifs qui semblent corrects, mais échouent :
- Ajouter
COALESCEdirectement autour d'une requête qui ne renvoie aucune ligne ne sert à rien ; il n'y a aucune ligne sur laquelleCOALESCEpuisse agir. IFNULL/ISNULLont la même limitation queCOALESCE.- Ajouter
LIMIT 1ne crée pas une ligne lorsqu'aucune ligne ne correspond.
Le problème du nombre de lignes doit être résolu avec l'encadrement par sous-requête scalaire ou avec un agrégat, et non avec les seules fonctions de substitution de NULL.
Exemple détaillé : demander la troisième valeur alors qu'il n'y en a que deux
Salaires : 500, 500, 300. Les salaires distincts sont simplement 500 et 300, il n'existe donc pas de troisième valeur la plus élevée.
- DENSE_RANK simple avec WHERE rnk = 3: renvoie zéro ligne. L'exigence n'est pas respectée.
- Encadrement par sous-requête scalaire: la requête interne ne trouve rien, le SELECT externe renvoie donc une ligne :
NULL. L'exigence est respectée. - COALESCE(..., 0): renvoie une ligne :
0, si une valeur numérique par défaut était demandée.
L'expliquer pendant l'entretien
Gagnez des points en explicitant votre raisonnement :
- « La requête naïve renvoie un ensemble vide, et non NULL ; je vais donc l'encapsuler dans une sous-requête scalaire pour garantir une ligne. »
- « Une sous-requête scalaire sans ligne correspondante s'évalue à NULL, ce qui correspond exactement au contrat. »
- « Si vous préférez une valeur par défaut comme 0 plutôt que NULL, j'ajouterai COALESCE autour de la sous-requête. »
Montrer que vous comprenez la différence entre la sémantique du nombre de lignes et celle de la valeur constitue tout l'objectif de cette question.
Tout rassembler
Une solution robuste et paramétrable pour obtenir la Nᵉ valeur la plus élevée ou NULL : classez les salaires distincts, filtrez sur le rang N dans une sous-requête scalaire et laissez le SELECT externe garantir une seule ligne.
Cette requête gère les doublons (avec DENSE_RANK), se généralise à toute valeur de N et renvoie NULL proprement lorsque N dépasse le nombre de salaires distincts.
SELECT (
SELECT salary
FROM (
SELECT salary,
DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
FROM employee
) t
WHERE rnk = :n
LIMIT 1
) AS nth_highest;Vérification rapide
Réfléchissez au nombre de lignes par rapport aux valeurs NULL.
Récapitulatif
Lorsque N dépasse le nombre de salaires distincts disponibles, une simple requête de classement renvoie un ensemble vide, et non NULL.
- Encapsulez la requête de la Nᵉ valeur la plus élevée dans une sous-requête scalaire au sein d'un SELECT externe afin qu'elle produise toujours une ligne et renvoie
NULLlorsqu'aucune valeur ne correspond. - La forme MAX sous MAX renvoie
NULLsans effort dans le cas de la deuxième valeur la plus élevée. - COALESCE ne substitue une valeur qu'une fois qu'une ligne existe ; cette fonction ne peut pas transformer zéro ligne en une ligne.
Faites toujours la distinction entre le nombre de lignes et la valeur lorsqu'un intervieweur demande une gestion élégante de NULL.
Questions Fréquemment Posées
La leçon « Renvoyer NULL lorsqu’il n’existe aucune n-ième valeur » est-elle gratuite ?
Oui — le texte complet de « Renvoyer NULL lorsqu’il n’existe aucune n-ième valeur » 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 Coding Interview Prep, passe à CoddyKit PRO. Le cours Coding Interview Prep comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Renvoyer NULL lorsqu’il n’existe aucune n-ième valeur » ?
Le cas particulier apprécié des recruteurs : gérer élégamment un nombre insuffisant de lignes Tu pratiques Coding 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 Coding Interview Prep ?
Aucune expérience préalable n'est requise. Coding 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 4 sur 4.
Combien de temps prend la leçon « Renvoyer NULL lorsqu’il n’existe aucune n-ième valeur » ?
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 Coding Interview Prep ?
Oui. Chaque leçon Coding 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
- Deuxième salaire le plus élevé : cinq méthodes
- N-ième valeur la plus élevée avec DENSE_RANK
- Le plus gros salaire par service
- Renvoyer NULL lorsqu’il n’existe aucune n-ième valeur