| この記事の要点 |
|
CASE 式と NULL 判定
SQL の CASE 式で「NULL なら別の値、そうでなければそのまま」のような条件分岐を書く場面はよくあります。ところが NULL の判定には独特のルールがあり、= で書くと意図通りに動きません。
NG 例 — = NULL は機能しない
-- これは意図通りに動かない!
SELECT
CASE WHEN col1 = NULL THEN col2 ELSE col1 END
FROM test_table;
SQL の三値論理(true / false / NULL)では、NULL = NULL は true ではなく NULL を返します。WHEN は true のときだけ THEN 側を返すため、結局すべての行で ELSE col1 が選ばれてしまいます。
正しい書き方 — IS NULL
SELECT
CASE WHEN col1 IS NULL THEN col2 ELSE col1 END
FROM test_table;
NULL の判定には専用の演算子 IS NULL / IS NOT NULL を使います。これは = と違って必ず true / false を返す点が重要です。
具体例
テーブル
| id | col1 | col2 |
|---|---|---|
| 1 | A | X |
| 2 | NULL | Y |
| 3 | C | Z |
クエリ
SELECT
id,
CASE WHEN col1 IS NULL THEN col2 ELSE col1 END AS result
FROM test_table;
結果
| id | result |
|---|---|
| 1 | A |
| 2 | Y |
| 3 | C |
もっと簡潔に — COALESCE
COALESCE は引数を左から順に評価し、最初に NULL でない値を返す関数。ANSI SQL 標準で、ほぼ全ての RDBMS で使えます。
-- CASE 式と同じ結果
SELECT COALESCE(col1, col2) FROM test_table;
-- 3 つ以上もOK
SELECT COALESCE(col1, col2, col3, 'デフォルト') FROM test_table;
RDBMS 別の関数比較
| RDBMS | 関数 | 例 |
|---|---|---|
| 標準 SQL / 全DB | COALESCE | COALESCE(col1, col2) |
| Oracle | NVL | NVL(col1, col2) |
| Oracle | NVL2 | NVL2(col1, 値1, 値2) |
| SQL Server | ISNULL | ISNULL(col1, col2) |
| MySQL | IFNULL | IFNULL(col1, col2) |
| MySQL | IF | IF(col1 IS NULL, col2, col1) |
逆パターン — IS NOT NULL
「NULL じゃないなら〜」を判定したい場合は IS NOT NULL。
SELECT
CASE WHEN email IS NOT NULL THEN '連絡可' ELSE '連絡不可' END AS status
FROM users;
NULLIF — 値を NULL に変換
逆に「ある値を NULL として扱いたい」場面では NULLIF が便利。2 つの引数が等しいとき NULL を返します。
-- 空文字を NULL として扱う
SELECT NULLIF(name, '') FROM users;
-- 数値の 0 を NULL に
SELECT NULLIF(count, 0) FROM stats;
-- 0 除算回避
SELECT amount / NULLIF(divisor, 0) AS result FROM transactions;
WHERE 句での NULL 判定
CASE 内に限らず、WHERE でも = ではなく IS NULL を使います。
-- NG: 何も返らない
SELECT * FROM users WHERE deleted_at = NULL;
-- OK: 削除されていないユーザー
SELECT * FROM users WHERE deleted_at IS NULL;
-- 削除済みユーザー
SELECT * FROM users WHERE deleted_at IS NOT NULL;
三値論理 — ANDやORの結果
| A | B | A AND B | A OR B |
|---|---|---|---|
| true | NULL | NULL | true |
| false | NULL | false | NULL |
| NULL | NULL | NULL | NULL |
NULL を含む論理演算は「不明」として扱われます。最終的な WHERE 句が NULL になった行は、結果に含まれません。
NOT IN と NULL の落とし穴
-- NULL が含まれる集合に NOT IN すると何も返らない
SELECT * FROM users
WHERE id NOT IN (SELECT user_id FROM ng_list); -- ng_list に NULL あり → 0 件
-- 対策: NOT EXISTS を使う
SELECT * FROM users u
WHERE NOT EXISTS (
SELECT 1 FROM ng_list n WHERE n.user_id = u.id
);
CASE 式の 2 つの構文
1. 検索 CASE(推奨)
CASE
WHEN col1 IS NULL THEN '不明'
WHEN col1 = 'A' THEN 'アルファ'
WHEN col1 = 'B' THEN 'ベータ'
ELSE 'その他'
END
2. 単純 CASE
-- 単純 CASE では NULL を判定できない(= で比較するため)
CASE col1
WHEN 'A' THEN 'アルファ'
WHEN 'B' THEN 'ベータ'
ELSE 'その他'
END
NULL を扱うなら必ず検索 CASEを使いましょう。
FAQ
Q: NULL を含むカラムでソートするとどうなる?
A: ORDER BY における NULL の扱いは RDBMS 依存。NULLS FIRST / NULLS LAST を明示することで制御できます(PostgreSQL / Oracle 等で対応)。
Q: COALESCE と IFNULL のどちらを使うべき?
A: 移植性を考えるなら COALESCE(標準 SQL)。MySQL 専用なら IFNULL でも可。
Q: 集計関数(SUM / COUNT 等)の NULL は?
A: SUM / AVG / MIN / MAX はNULL を無視。COUNT は COUNT(*) なら NULL 行も数え、COUNT(col) なら NULL を除いた行数。
関連
- CASE式 — 条件分岐の標準構文
- COALESCE — 最初の非 NULL を返す
- NVL — Oracle の NULL 置換
- ISNULL — SQL Server / MySQL の NULL 置換
- IS NULL — NULL 判定演算子
子ページはありません
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- プロジェクトをTomcatプロジェクトとして認識させる方法 2026-10-07 22:32:50
- MySQLの1366 Incorrect string value|Laravelの文字コード・絵文字エラー 2026-10-07 21:54:03
- curlの証明書ホスト名不一致|旧エラー51・現行60の確認と対処 2026-10-07 21:54:03
- LaravelのMassAssignmentException|fillableの原因と安全な対処 2026-10-07 21:54:03
- Eclipse で Tomcat の起動ログがコンソールに出ない時の確認手順 2026-10-07 21:54:02
- MySQLにおける中央値(Median)の導き方(バージョン8未満) 2026-10-07 13:49:45
- getInputForward 2026-10-07 13:41:15
- JSONから配列に変換 2026-10-07 13:41:15
- ビューから値をモデルに格納しコントローラーで受け取る方法 2026-10-07 13:23:41
- Laravelのテーブル作成と定義変更|マイグレーション・up/down・注意点 2026-10-07 13:23:41
- NumPy 配列に要素を追加する方法 (append / concatenate) 2026-10-07 13:23:41
- MariaDB・MySQLで現在日時を取得する方法|NOW・タイムゾーン・保存型 2026-10-07 13:13:36
- 【django】テンプレートで定数を使用する方法 2026-10-07 13:10:15
- Spring BootにおけるApplication.propertiesの環境依存設定の分割方法 2026-10-07 12:09:35
- Not supported for DML operations【Springエラー】 2026-10-07 11:09:38