SQLで割合を計算するとき、分母が0になってゼロ除算エラーになるなら、分母をNULLIF(分母, 0)に置き換えるのが簡潔な対処です。NULLIFは2つの値が等しいときNULLを返すため、分母0をNULLへ変換できます。SQL ServerやPostgreSQLでは、この形でゼロ除算を避けられます。結果のNULLを0へ変えたい場合はCOALESCEを追加できますが、『計算不能』を『0%』へ置き換えてよいかは業務上の意味を確認してください。
まずゼロ除算をNULLIFで直す
たとえば成功件数を総件数で割る割合計算で、総件数が0になるケースを考えます。分母をそのまま使うのではなく、NULLIFで0だけをNULLへ変換します。
SELECT
100.0 * success_count / NULLIF(total_count, 0) AS success_rate
FROM daily_stats;
total_countが0ならNULLIF(total_count, 0)はNULLになります。分母が0以外なら元のtotal_countが返るため、通常の行はそのまま計算できます。
NULLIFは何をしているのか
NULLIF(a, b)は、aとbが等しいときNULLを返し、等しくなければaを返す式です。ゼロ除算対策では『分母が0ならNULLにする』という小さな条件分岐として使います。
| total_count | NULLIF(total_count, 0) | 結果 |
|---|---|---|
| 10 | 10 | 通常計算 |
| 1 | 1 | 通常計算 |
| 0 | NULL | 計算結果はNULL |
用語解説:NULLIF
2つの式が等しいときNULLを返し、異なるときは第1引数を返すSQLの条件式です。
COALESCEで0を返すときの注意
画面や集計仕様でNULLではなく0を返す必要がある場合は、計算結果をCOALESCEで包めます。
SELECT
COALESCE(100.0 * success_count / NULLIF(total_count, 0), 0) AS success_rate
FROM daily_stats;
ただし総件数0の状態は、本来は『割合を計算できない』状態です。それを0%と表示すると意味が変わる場合があります。NULLのまま返すか0へ変換するかは、表示仕様や集計ルールに合わせて決めてください。
用語解説:COALESCE
左から順に評価し、最初にNULLではない値を返すSQLの条件式です。NULL時の代替値を指定するときに使います。
CASE式で書く方法との違い
SELECT
CASE
WHEN total_count = 0 THEN NULL
ELSE 100.0 * success_count / total_count
END AS success_rate
FROM daily_stats;
分母0だけをNULLにするならNULLIFのほうが短く書けます。一方、0のときに特別な値を返す、複数条件で処理を変えるなど条件分岐が増える場合はCASE式のほうが意図を読み取りやすくなります。
実務で確認したい4つのポイント
- どの列が分母になるかを先に確認する
- 分母0をNULLとして扱うか、0として表示するか仕様を決める
- 整数同士の除算や型変換は利用DBの数値型ルールを確認する
- 複雑な条件ならNULLIFだけで詰め込まずCASE式へ切り替える
NULLIFはゼロ除算を隠すための万能な処理ではありません。0件が発生する理由そのものがデータ不備なら、クエリだけでなく集計条件や元データも確認してください。
関連するSQLのNULL・条件分岐
NULLそのものの扱いを整理したい場合はNULL解説、複数条件で結果を切り替えたい場合はCASE式の記事が参考になります。SQL全体の構文を確認したい場合はコマンド一覧も使えます。
(SQLのNULLとCOALESCEを整理するについては『SQL NULL完全攻略|IS NULL・COALESCEの使い分けとDB別バグ防止術5選』をご参照ください)
(CASE式で条件分岐するについては『SQL CASE式の使い方|SELECT・WHERE・UPDATEで条件分岐する書き方とつまずき解消実例』をご参照ください)
(SQLコマンドをまとめて確認するについては『SQLコマンド一覧21選|シーン別で迷わない使い方+チートシート』をご参照ください)
よくある疑問
NULLIF(0, 0)は何を返す?
NULLを返します。ゼロ除算対策では、この性質を使って分母の0だけをNULLへ変換します。
COALESCEで必ず0にしたほうがよい?
必ずではありません。分母0が『割合を計算できない』意味なら、NULLを0%へ変えると意味が変わるため仕様に合わせて判断します。
NULLIFとCASEはどちらが速い?
この記事では性能の優劣を一般化しません。単純な分母0の置換ならNULLIFは簡潔で、複雑な条件分岐ならCASEのほうが意図を表しやすいという可読性の観点で選びます。
まとめ
ゼロ除算を避ける最小の修正は、分母をNULLIF(分母, 0)にすることです。結果のNULLを0へ変えるならCOALESCEを組み合わせられますが、その変換が業務上正しいかを確認してください。条件が増えるならCASE式へ切り替えると、意図を保ちやすくなります。
まずゼロ除算が起きるクエリの分母を確認し、NULLIFで0だけをNULLにした結果をテストしてみてください。