0Pricing
SQL Interview Prep · レッスン

三値論理とUNKNOWN

NULL = NULLがTRUEにならない理由と、条件の中でUNKNOWNが伝播する仕組みを学びます。

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

NULLが候補者を悩ませる理由

NULLは、SQLの面接で間違った回答を生む最大の要因です。落とし穴は、NULLを通常の値として扱ってしまうことです。実際には、NULLは「不明」または「欠落」を意味し、ゼロでも空文字列でもありません。

面接官がこの問題を好むのは、構文は正しそうに見えるのに、結果がひそかに間違うからです。「行を返すはずの」フィルターを示して、なぜ何も返さないのかを尋ねることがあります。

このレッスンでは、NULLに関するあらゆる質問に対応できる考え方、つまり3値論理を身につけます。比較結果がTRUE、FALSE、UNKNOWNのいずれかになることを理解すれば、後は自然に説明できます。

NULLは値ではない

面接で口にすべき最も重要な一文は、NULLは値そのものではなく、値が存在しないことを表すということです。

そのため、数値を比較するように = で比較することはできません。データベースには、2つの不明な値が等しいかどうかを判断できないため、TRUEともFALSEとも断定しません。

  • NULL = 5 はFALSEではなくUNKNOWNです
  • NULL = NULL はTRUEではなくUNKNOWNです
  • NULL <> NULL もUNKNOWNです

このため、NULLを許容する列に単純な等価比較のフィルターを使うと、行がひそかに除外されます。

2値論理と3値論理

多くのプログラミング言語では2値論理を使います。式の結果はTRUEまたはFALSEのどちらかです。SQLでは、NULLが比較に関わると3つ目の結果であるUNKNOWNが加わります。

つまりSQLの述語は、TRUE、FALSE、UNKNOWNの3つの結果のいずれかになります。WHERE句は、述語が厳密にTRUEになった場合にだけ行を残します。フィルタリングではUNKNOWNはFALSEと同じように扱われますが、論理的には同じものではありません。

面接官がこの違いを確認するのは、UNKNOWNがFALSEとは異なり、NOT の下で別の振る舞いをするからです。

行をひそかに除外するフィルター

典型的な例を見てみましょう。bonus がNULLになることがあるとします。採用担当者が次のように尋ねます。「このクエリはボーナスが1000ではない全員を返すはずです。なぜボーナスがない従業員を除外するのでしょうか」

bonus がNULLの行では、bonus <> 1000 の結果はTRUEではなくUNKNOWNです。WHEREはTRUEの行だけを残すため、その従業員は結果から消えます。

NULLを明示的に扱うことが解決策ですが、その方法は次のレッスンで説明します。ここでは、欠落した行がバグではなく、論理の結果であることを理解してください。

SELECT name, bonus
FROM employees
WHERE bonus <> 1000;
-- Rows where bonus IS NULL are excluded:
-- NULL <> 1000 evaluates to UNKNOWN, not TRUE

AND式におけるNULL

3値論理では、AND の振る舞いが変わります。このルールを覚えておけば、面接でどのような真理値表の質問をされても、その場で答えられます。

  • TRUE AND UNKNOWN = UNKNOWN
  • FALSE AND UNKNOWN = FALSE
  • UNKNOWN AND UNKNOWN = UNKNOWN

直感的には、AND は1つでもFALSEがあれば、結果を確実にFALSEにできます。そのため、FALSE AND 何であってもFALSEのままです。一方、TRUE AND UNKNOWNは依然としてUNKNOWNです。不明な側がどちらの結果になる可能性もあるためです。

-- If status = 'active' is TRUE but bonus = 100 is UNKNOWN:
SELECT *
FROM employees
WHERE status = 'active' AND bonus = 100;
-- Combined result is UNKNOWN, so the row is NOT returned

OR式におけるNULL

OR は AND と対照的な振る舞いをします。1つでもTRUEがあれば結果を確実にTRUEにできるため、TRUEによってUNKNOWNの影響がなくなります。

  • TRUE OR UNKNOWN = TRUE
  • FALSE OR UNKNOWN = UNKNOWN
  • UNKNOWN OR UNKNOWN = UNKNOWN

つまり、OR条件の一方の分岐がUNKNOWNでも、もう一方の分岐が明確にTRUEであれば、その行は条件に一致します。これは、ANDに関する質問の後によく出される追加質問です。

SELECT *
FROM employees
WHERE department = 'Sales' OR bonus = 100;
-- A Sales employee with NULL bonus:
-- TRUE OR UNKNOWN = TRUE, so the row IS returned

NOTはTRUEとFALSEを反転するがUNKNOWNは変えない

最後に面接官が出す、微妙なポイントです。NOT はTRUEをFALSEに、FALSEをTRUEに反転しますが、NOT UNKNOWNはUNKNOWNのままです。

そのため、失敗した条件を単に NOT で囲んでも、結果を反転させることはできません。NULLの行で bonus = 1000 がUNKNOWNなら、NOT (bonus = 1000) もUNKNOWNなので、その行はやはり除外されます。

否定によってNULLの行を救うことはできません。救えるのは、明示的な IS NULL テストだけです。

-- For a row where bonus IS NULL:
--   bonus = 1000        -> UNKNOWN
--   NOT (bonus = 1000)  -> UNKNOWN  (still excluded)
SELECT * FROM employees WHERE NOT (bonus = 1000);

実例:NOT INの落とし穴

これは、NULLに関する質問で最もよく出されるものの1つです。NULLを含むリストに対して NOT IN を使うと、NULLを単に無視すると思っている候補者を驚かせることに、行がまったく返されません。

内部的には、x NOT IN (1, 2, NULL) は x <> 1 AND x <> 2 AND x <> NULL に展開されます。最後の比較がUNKNOWNになり、TRUE AND TRUE AND UNKNOWNの結果はUNKNOWNになるため、条件を満たす行はなくなります。

安全な代替手段は NOT EXISTS です。これはこの問題の影響を受けません。

-- Returns ZERO rows if the subquery yields any NULL
SELECT name
FROM employees
WHERE manager_id NOT IN (SELECT manager_id FROM managers);

-- Each comparison against NULL becomes UNKNOWN,
-- and the AND-chain collapses to UNKNOWN for every row.

WHEREでUNKNOWNがFALSEのように振る舞う理由

よくある追加質問は次のとおりです。「UNKNOWNはFALSEではないのに、なぜFALSEの行と同じように除外されるのですか」

正確な答えは、WHERE、ON、HAVINGがすべてTRUEだけを残すルールを使うからです。FALSEとUNKNOWNはどちらもこの判定に失敗するため、フィルタリングでは同じように見えます。

違いが現れるのは、否定とCHECK制約の場合だけです。CHECK制約は条件がTRUEまたはUNKNOWNのときに行を通すため、ブロックできると思っていたCHECKをNULLがすり抜けることがあります。

-- CHECK passes on TRUE or UNKNOWN, so NULL salary is allowed:
-- CONSTRAINT salary_positive CHECK (salary > 0)
-- INSERT ... salary = NULL  -> NULL > 0 is UNKNOWN -> allowed

より深い例:COUNTと真偽値のギャップ

現実的な面接問題で、ここまでの内容を結び付けてみましょう。「従業員が100人います。SELECT COUNT(*) WHERE bonus = 100 は30を返し、WHERE bonus <> 100 は50を返します。残りの20人はどこにいるのでしょうか」

残りの20人のボーナスはNULLです。= 100 も <> 100 も、その従業員に対してTRUEにはならず、どちらもUNKNOWNになるため、両方のフィルターを通り抜けてしまいます。

「NULLはどちらの述語も満たさないため、分類した件数の合計が全体の件数と一致しません」と答えれば、面接官がまさに求めている回答になります。

SELECT
  COUNT(*) FILTER (WHERE bonus = 100)  AS eq_100,
  COUNT(*) FILTER (WHERE bonus <> 100) AS ne_100,
  COUNT(*) FILTER (WHERE bonus IS NULL) AS null_bonus,
  COUNT(*) AS total
FROM employees;

面接で押さえるポイント

NULLの論理が話題になったら、シニアらしさを示すために次の点を押さえてください。

  • NULLは不明を意味し、NULLとの比較結果はUNKNOWNになります。
  • SQLは3値論理、つまりTRUE、FALSE、UNKNOWNを使います。
  • WHERE、ON、HAVINGはTRUEの行だけを残します。
  • NOT UNKNOWN もUNKNOWNのままなので、否定してもNULLの行は復元されません。
  • NULLを1つでも含む NOT IN は行を返しません。代わりに NOT EXISTS を使います。

まずモデルを説明し、その後で真理値表を順に説明してください。そうすれば、単なる暗記ではなく、理由まで理解していることが伝わります。

確認問題

3値論理をどの程度理解できているか確認しましょう。

まとめ

これで、NULLについての基本的な考え方を身につけました。

  • NULLは不明であり、値ではありません。= や <> で比較してはいけません。
  • SQLは3値論理を使い、述語はTRUE、FALSE、UNKNOWNのいずれかを返します。
  • フィルタリング句はTRUEだけを残します。UNKNOWNの行はFALSEの行と同じように消えます。
  • NOT はTRUEとFALSEを反転しますが、UNKNOWNは変えません。
  • NOT IN とNULLの組み合わせは0行を返します。その場合は NOT EXISTS を使います。

次は、IS NULL、IS NOT NULL、NULL安全な等価演算子を使って、NULLを正しく検査する方法を学びます。

よくある質問

「三値論理とUNKNOWN」レッスンは無料ですか?

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

「三値論理とUNKNOWN」で何を学びますか?

NULL = NULLがTRUEにならない理由と、条件の中でUNKNOWNが伝播する仕組みを学びます。 ブラウザで直接実行するハンズオンコードでSQL Interview Prepを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

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

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

「三値論理とUNKNOWN」レッスンにはどのくらい時間がかかりますか?

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

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

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

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

  1. 三値論理とUNKNOWN
  2. IS NULL、IS NOT NULL、NULLセーフな等価比較
  3. COALESCE、NULLIF、ISNULL
  4. 集計、JOIN、DISTINCTにおけるNULL
← SQL Interview Prepに戻る