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 NULLIS 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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 三値論理とUNKNOWN
- IS NULL、IS NOT NULL、NULLセーフな等価比較
- COALESCE、NULLIF、ISNULL
- 集計、JOIN、DISTINCTにおけるNULL