0Pricing
Coding Interview Prep · レッスン

IS NULL、IS NOT NULL、NULLセーフな等価比較

NULLを正しく検査する方法と、各方言のNULLセーフ演算子を学びます。

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

NULLを正しく検査する

前のレッスンで、NULLを検索するために = は使えないことを確認しました。それでは、実際にはどのように検査すればよいのでしょうか。専用の述語である IS NULL と IS NOT NULL を使います。

欠落した値を確認する、標準SQLとして正しく移植性のある方法はこれらだけです。面接官は col = NULL を見つけると、必ず不正解とします。

このレッスンでは、IS NULL、IS NOT NULL、IS DISTINCT FROMファミリー、そして方言ごとに異なるNULL安全な等価演算子を扱います。データベース間の違いを理解していることは、シニアとしての強いアピールになります。

IS NULLとIS NOT NULL

IS NULL は値がNULLのときにTRUEを返し、それ以外ではFALSEを返します。重要なのは、UNKNOWNを返すことが決してないため、WHEREでそのまま安全に使えることです。

IS NOT NULL はその正確な補集合です。実際の値があればTRUEを、NULLならFALSEを返します。

これらの述語は、NULLを扱う際の基本となるものです。標準SQLであり、MySQL、Postgres、SQL Server、Oracle、SQLiteで同じように動作します。

-- Find employees with no recorded bonus
SELECT name FROM employees WHERE bonus IS NULL;

-- Find employees that do have a bonus
SELECT name FROM employees WHERE bonus IS NOT NULL;

col = NULLが常に誤りである理由

面接で必ず出る落とし穴です。候補者が欠落したボーナスを検索しようとして WHERE bonus = NULL と書いたとします。このクエリは0行を返します。

3値論理を思い出してください。bonus = NULL は、NULLの行も含めてすべての行でUNKNOWNになります。不明な値と等しいものはないからです。WHEREはTRUEだけを残すため、何も一致しません。

非標準モードの一部のデータベースでは、= NULL をひそかに IS NULL に書き換えることがあります。しかし、それを当てにしてはいけません。必ず IS NULL と明示的に書いてください。

-- WRONG: returns zero rows, bonus = NULL is UNKNOWN for all
SELECT name FROM employees WHERE bonus = NULL;

-- RIGHT:
SELECT name FROM employees WHERE bonus IS NULL;

NULLと非NULLの件数を数える

よくある分析作業に、データ品質の監査があります。列の値がどの程度埋まっているかを調べる作業です。IS NULLとCOUNTを組み合わせて、欠落した値を報告します。

違いに注目してください。COUNT(*) はすべての行を数える一方、COUNT(bonus) はNULLでないボーナスだけを数えます。この2つの差がNULLの件数になります。この点は集計のレッスンで改めて扱います。

SELECT
  COUNT(*)                                AS total_rows,
  COUNT(bonus)                            AS with_bonus,
  COUNT(*) - COUNT(bonus)                 AS missing_bonus,
  SUM(CASE WHEN bonus IS NULL THEN 1 ELSE 0 END) AS missing_check
FROM employees;

NULL安全な等価比較が解決する問題

2つの列を照合し、「両方がNULL」の場合も一致として扱いたいとします。通常の a = b ではうまくいきません。両方がNULLのとき結果はUNKNOWNになるため、直感的には「同じ」であるにもかかわらず、その組み合わせは除外されます。

これは、変更を検出するために古い行と新しい行を比較するときや、任意項目を結合条件にするときに発生します。NULLとNULLならTRUE、NULLと値ならFALSEになる比較が必要です。それを提供するのがNULL安全な等価比較です。

-- Goal: change-detection where two NULLs count as equal
-- Plain equality fails when both sides are NULL:
--   NULL = NULL -> UNKNOWN (treated as not-equal)
SELECT * FROM old_t o JOIN new_t n ON o.id = n.id
WHERE o.note = n.note;  -- misses rows where both notes are NULL

IS DISTINCT FROM(標準SQL)

ANSI標準のNULL安全な比較演算子は IS DISTINCT FROM と、その逆の IS NOT DISTINCT FROM です。Postgres、SQL Server(2022以降)などでサポートされています。

  • a IS NOT DISTINCT FROM b は、「NULL = NULLも等しいとみなした等価」を意味します。
  • a IS DISTINCT FROM b は、「NULLを通常の値として扱った非等価」を意味します。

これらは常にTRUEまたはFALSEを返し、UNKNOWNにはならないため、述語が必要な場所で安全に使えます。

-- TRUE when notes match, including both NULL
SELECT * FROM old_t o JOIN new_t n ON o.id = n.id
WHERE o.note IS NOT DISTINCT FROM n.note;

-- TRUE when notes differ (NULL vs value counts as different)
SELECT * FROM old_t o JOIN new_t n ON o.id = n.id
WHERE o.note IS DISTINCT FROM n.note;

MySQLの<=>演算子

MySQLには、<=> と記述する簡潔なNULL安全の等価演算子があります(spaceship演算子)。

a <=> b は、両辺が等しい場合、または両辺がNULLの場合に1(TRUE)を返し、それ以外では0(FALSE)を返します。これはMySQLにおける IS NOT DISTINCT FROM と同等です。

MySQLでNULL安全な照合を求められた場合、これが慣用的な答えです。

-- MySQL: 1 when both equal or both NULL
SELECT (NULL <=> NULL) AS both_null,   -- 1
       (NULL <=> 5)    AS null_vs_val, -- 0
       (5 <=> 5)       AS val_eq;      -- 1

SELECT * FROM old_t o JOIN new_t n ON o.id = n.id
WHERE o.note <=> n.note;

SQL方言別チートシート

面接官は、移植性の境界を理解している候補者を高く評価します。NULL安全な等価比較の対応表は次のとおりです:

  • ANSI / Postgres / SQL Server 2022+: IS NOT DISTINCT FROM
  • MySQL / MariaDB: <=>
  • SQLite: IS と IS NOT はNULL安全な等価比較として機能します
  • Oracle: ネイティブ演算子はありません。DECODE(a, b, 1, 0) = 1 またはCOALESCEを使った方法でエミュレートします

使用するデータベースエンジンが不明な場合は、次に示す移植性の高い手動形式に切り替えてください。

-- SQLite NULL-safe equality
SELECT * FROM t WHERE a IS b;      -- TRUE when both NULL
SELECT * FROM t WHERE a IS NOT b;  -- complement

移植性の高い手動NULL安全等価比較

ネイティブ演算子が使えない場合は、基本的な条件からNULL安全な等価比較を組み立てられます。移植性の高いパターンでは、通常の等価比較と、両方がNULLであることを明示する条件を組み合わせます。

これは「等しい、または両方とも値がない」と読めます。すべてのデータベースで動作するため、面接官が方言を特定していない場合の回答として最適です。

SELECT *
FROM old_t o JOIN new_t n ON o.id = n.id
WHERE (o.note = n.note)
   OR (o.note IS NULL AND n.note IS NULL);

-- Alternative using COALESCE with a sentinel that
-- cannot occur in real data:
-- WHERE COALESCE(o.note, '##NULL##') = COALESCE(n.note, '##NULL##')

発展例:NULL安全なJOINキー

現実的な落とし穴として、NULLを許容するキーでJOINするケースがあります。regionが両側でNULLになる可能性がある場合、通常の等価JOINではNULL = NULLがUNKNOWNになるため、それらの組み合わせが暗黙に除外されます。

「地域がない行同士は、それでも一致させる」という業務ルールであれば、JOIN条件をNULL安全にする必要があります。面接ではその前提を声に出して説明し、使用するエンジンに合った演算子を選んでください。

-- Postgres / ANSI: match including both-NULL regions
SELECT a.id, b.id
FROM table_a a
JOIN table_b b
  ON a.region IS NOT DISTINCT FROM b.region;

-- MySQL equivalent: ON a.region <=> b.region

面接でのポイント

NULLテストに関する質問には、次のように明確に対応してください:

  • 常にIS NULL / IS NOT NULLを使用し、= NULLは決して使用しないでください。
  • これらの述語はTRUEまたはFALSEのみを返すため、WHERE句で安全に使用できます。
  • 「NULLとNULLを等しいものとして一致させる」場合は、IS NOT DISTINCT FROM(ANSI)または<=>(MySQL)を使用してください。
  • 対象とする方言を明示し、不明な場合は移植性の高いOR条件による代替方法を提示してください。

標準演算子とベンダー固有の演算子の両方を挙げると、選考担当者に幅広い知識が伝わります。

確認問題

正しいNULL安全比較を選んでください。

まとめ

これでNULLを正しくテストできるようになりました:

  • IS NULL / IS NOT NULLだけが正しく、移植性のあるNULLテストです。UNKNOWNを返すことはありません。
  • col = NULLは常に0行になります。これは面接でよくある落とし穴です。
  • NULL安全な等価比較では、2つのNULLを等しいものとして扱います:IS NOT DISTINCT FROM(ANSI/Postgres)、<=>(MySQL)、IS(SQLite)。
  • 演算子がない場合は、(a = b) OR (a IS NULL AND b IS NULL)を使用してください。

次は、COALESCE、NULLIF、ISNULLなどのベンダー固有関数を使ってNULLをデフォルト値に置き換える方法です。

よくある質問

「IS NULL、IS NOT NULL、NULLセーフな等価比較」レッスンは無料ですか?

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

「IS NULL、IS NOT NULL、NULLセーフな等価比較」で何を学びますか?

NULLを正しく検査する方法と、各方言のNULLセーフ演算子を学びます。 ブラウザで直接実行するハンズオンコードでCoding Interview Prepを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

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

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

「IS NULL、IS NOT NULL、NULLセーフな等価比較」レッスンにはどのくらい時間がかかりますか?

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

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

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

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

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