n番目の値がない場合にNULLを返す
面接で好まれる、行数が少なすぎる場合を適切に処理するエッジケースを学びます。
「n番目の値がない場合にNULLを返す」はCoddyKit上の無料SQL Interview Prepレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSQL Interview Prep学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 SQL 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チューター)、SQL Interview Prepコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 SQL Interview Prepコースには全4レッスンが含まれています。
「n番目の値がない場合にNULLを返す」で何を学びますか?
面接で好まれる、行数が少なすぎる場合を適切に処理するエッジケースを学びます。 ブラウザで直接実行するハンズオンコードでSQL Interview Prepを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
SQL Interview Prepを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのSQL Interview Prepは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「n番目の値がない場合にNULLを返す」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このSQL Interview Prepレッスンでコードを書いて実行できますか?
はい。すべてのSQL Interview Prepレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 2番目に高い給与を求める5つの方法
- DENSE_RANKでn番目に高い値を求める
- 部署ごとの最高給与者
- n番目の値がない場合にNULLを返す