0Pricing
Coding Interview Prep · レッスン

n番目の値がない場合にNULLを返す

面接で好まれる、行数が少なすぎる場合を適切に処理するエッジケースを学びます。

「n番目の値がない場合にNULLを返す」はCoddyKit上の無料Coding Interview Prepレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはCoding Interview Prep学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Coding Interview Prepコースには全4レッスンが含まれています。

面接官が好んで出すエッジケース

N番目に高い給与を求めるクエリを正しく書けたところで、面接官が次のように尋ねることがあります。「テーブルにN種類未満の給与しかない場合はどうしますか。空の結果ではなく、NULLを1つだけ返してください」

この質問は、クエリを暗記しただけの候補者と、結果セットの動作を理解している候補者を分けるポイントです。多くの解答は、NULLを含む1行ではなく、0行を返してしまいます。

このレッスンでは、出力を必ず1行にし、N番目の値が存在しない場合はその値をNULLにする方法を学びます。

DENSE_RANKだけでは行が返らない理由

標準的なN番目に高い給与を求めるクエリを思い出してください。異なる給与が2種類しかない状態で3番目を求めると、WHERE rnk = 3に一致する行がないため、クエリは空の結果セット、つまり0行を返します。

空の結果セットは、NULLを含む1行とは異なります。仕様が「NULLを返す」となっている場合、元のロジックが正しくても、空の結果ではテストに失敗します。

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

修正方法1:外側のSELECTでラップする

最も簡単で確実な修正方法は、N番目に高い給与を求めるクエリ全体を、1つのSELECT内にあるスカラーサブクエリにすることです。一致する行がないスカラーサブクエリはNULLとして評価され、外側のSELECTは必ず1行を生成します。

これは、LeetCode形式の「NULLを返す」問題に対する典型的な解答であり、すべてのSQL方言で動作します。

SELECT (
  SELECT DISTINCT salary
  FROM employee
  ORDER BY salary DESC
  LIMIT 1 OFFSET 2   -- N = 3
) AS third_highest;

スカラーサブクエリの方法が機能する理由

次の2つのルールによって、目的の動作が実現します。

  • スカラーサブクエリは、最大で1つの値だけを返します。行を返さない場合、SQLはNULLを代入します。
  • FROM(または1行だけを返すデータソース)を持たない外側のSELECTは、常に1行を出力します。

つまり、内側のクエリがN番目の値を見つければその値が得られ、何も見つけなければNULLを保持する1行が得られます。これは、面接官が示した要件そのものです。

DENSE_RANK版に修正方法1を適用する

同じラッパーをウィンドウ関数による解法にも適用できます。ランキングを計算するクエリをスカラーサブクエリの中に入れ、N位の行がなければサブクエリがNULLを返すようにします。その場合も、外側のSELECTは1行を返します。

SELECT (
  SELECT salary
  FROM (
    SELECT salary,
           DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
    FROM employee
  ) t
  WHERE rnk = 3
) AS third_highest;

修正方法2:MAXなら自動的にNULLになる

レッスン1で学んだMAXを重ねる方法を思い出してください。0行に対する集約はNULLを返し、それでも1行を生成します。2番目に高い給与を求める場合は、これだけでNULLの要件を満たす簡潔な1行クエリになります。

ただし、純粋なMAXの入れ子を任意のNに拡張すると複雑になるため、これは特に2番目に高い値を求める場合に適しています。

SELECT MAX(salary) AS second_highest
FROM employee
WHERE salary < (SELECT MAX(salary) FROM employee);

修正方法3:COALESCEで代替値を指定する

環境によって1行が保証されているものの、別の理由で値が欠落する可能性がある場合は、結果をCOALESCEでラップして明示的なデフォルト値を指定できます。

注意点として、COALESCEが機能するのは、行がすでに存在する場合だけです。空の結果セットを行に変えることはできません。そのため、まずスカラーサブクエリのラッパー(行を保証します)と組み合わせ、そのうえでNULL以外の値、たとえば0を返したい場合にCOALESCEを使います。

SELECT COALESCE((
  SELECT DISTINCT salary
  FROM employee
  ORDER BY salary DESC
  LIMIT 1 OFFSET 2
), 0) AS third_highest_or_zero;

修正にならない方法

正しそうに見えても失敗する修正方法に注意してください。

  • 0行を返すクエリをCOALESCEで直接囲んでも何も起こりません。COALESCEが処理する行が存在しないためです。
  • IFNULLやISNULLにも、COALESCEと同じ制限があります。
  • LIMIT 1を追加しても、条件に一致する行がないときに行が作られるわけではありません。

行数の問題は、NULL置換関数だけでなく、スカラーサブクエリのラッパーまたは集約によって解決する必要があります。

実例:2つしかない値の3番目を求める

給与が500、500、300だとします。異なる給与は500と300だけなので、3番目に高い給与は存在しません。

  • WHERE rnk = 3を指定した通常のDENSE_RANK: 0行を返します。仕様を満たしません。
  • スカラーサブクエリのラッパー: 内側のクエリは何も見つけないため、外側のSELECTはNULLを含む1行を返します。仕様を満たします。
  • COALESCE(..., 0): 数値のデフォルト値が指定されている場合、0を含む1行を返します。

面接での説明方法

次のように説明すると評価されます。

  • 「単純なクエリはNULLではなく空の結果セットを返すため、1行を保証するためにスカラーサブクエリでラップします。」
  • 「一致する行がないスカラーサブクエリはNULLとして評価されるため、要件どおりです。」
  • 「NULLの代わりに0のようなデフォルト値が必要なら、サブクエリをCOALESCEで囲みます。」

行数と値の意味を区別して理解していることを示すのが、この質問の主な目的です。

すべてを組み合わせる

柔軟にNを指定できる、N番目に高い値またはNULLを返す堅牢な解法は、異なる給与をランキングし、スカラーサブクエリ内でN位に絞り込み、外側のSELECTで1行を保証する方法です。

この1つのクエリで、重複(DENSE_RANKによって処理)に対応し、任意のNに拡張でき、Nが異なる給与の種類数を超えた場合もNULLを適切に返せます。

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;

クイックチェック

行数とNULL値の違いについて考えてください。

まとめ

Nが存在する異なる給与の種類数を超えると、通常のランキングクエリはNULLではなく空の結果セットを返します。

  • N番目に高い値を求めるクエリを外側のSELECT内のスカラーサブクエリでラップします。これにより常に1行が生成され、一致する値がない場合はNULLになります。
  • MAXを重ねる方法は、2番目に高い値を求める場合に自動的にNULLを返します。
  • COALESCEは、行が存在する場合にのみ値を置き換えます。0行を1行に変えることはできません。

面接官からNULLを適切に処理するよう求められたら、行数と値を必ず区別してください。

よくある質問

「n番目の値がない場合にNULLを返す」レッスンは無料ですか?

はい。「n番目の値がない場合にNULLを返す」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Coding Interview Prepコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Coding Interview Prepコースには全4レッスンが含まれています。

「n番目の値がない場合にNULLを返す」で何を学びますか?

面接で好まれる、行数が少なすぎる場合を適切に処理するエッジケースを学びます。 ブラウザで直接実行するハンズオンコードでCoding Interview Prepを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Coding Interview Prepを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのCoding Interview Prepは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「n番目の値がない場合にNULLを返す」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このCoding Interview Prepレッスンでコードを書いて実行できますか?

はい。すべてのCoding Interview Prepレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 2番目に高い給与を求める5つの方法
  2. DENSE_RANKでn番目に高い値を求める
  3. 部署ごとの最高給与者
  4. n番目の値がない場合にNULLを返す
← Coding Interview Prepに戻る