0Pricing
SQL Interview Prep · Leçon

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 SQL 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 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 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 salaries

Correctif 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 COALESCE directement autour d'une requête qui ne renvoie aucune ligne ne sert à rien ; il n'y a aucune ligne sur laquelle COALESCE puisse agir.
  • IFNULL / ISNULL ont la même limitation que COALESCE.
  • Ajouter LIMIT 1 ne 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 NULL lorsqu'aucune valeur ne correspond.
  • La forme MAX sous MAX renvoie NULL sans 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 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 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 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 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 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

  1. Deuxième salaire le plus élevé : cinq méthodes
  2. N-ième valeur la plus élevée avec DENSE_RANK
  3. Le plus gros salaire par service
  4. Renvoyer NULL lorsqu’il n’existe aucune n-ième valeur
← Retour à SQL Interview Prep