Oracle 奇数・偶数を判定する方法 — NULLと負数も考慮した書き方

  • URLをコピーしました!

Oracleで奇数・偶数を判定したい場面は、ちょっとしたデータ抽出やフラグ付けなど、実務でも意外とよくあります。

MOD関数を使えばシンプルに実現できますが、NULLや負の数への対応、パフォーマンスや可読性といった観点も知っておくと安心です。

この記事では、基本的な使い方から注意点、代替手段まで、実務目線で解説していきます。

この記事を読むとわかること

  • OracleにおけるMOD関数を使った奇数・偶数判定の基本
  • NULLや負の値に対するMODの挙動と対策
  • BITAND関数を用いた高速な判定方法と可読性とのバランス
目次

MOD関数を使った基本の奇数・偶数判定

Oracleで奇数・偶数を判定するとき、一番よく使われるのが MOD 関数です。

MOD(値, 2) で2で割った余りを取得し、それが0なら偶数、1なら奇数というシンプルなロジック。文法的にも直感的で、初心者でもすぐ理解しやすいのが特徴です。

実務でもMODはSELECT文やWHERE句、PL/SQLのIF文などいろんな場面で使われています。

MOD(value, 2)でどう判定するか

まずは基本的な判定方法から確認しておきましょう。

SELECT
  value,
  MOD(value, 2) AS remainder
FROM
  sample_table;

このようにMOD関数で2を指定すると、余りが0か1で返ってきます。0なら偶数、1なら奇数です。

NULLが含まれてる場合のMOD関数の動き

MOD関数にNULLを渡した場合、戻り値もNULLになります

これはOracleの演算ルールに基づいており、「NULLを含む計算結果は基本的にNULLになる」という原則があります。つまり、MODを使った奇数・偶数の判定では、NULLがあると評価自体ができなくなるということです。

たとえば、以下のようなクエリを実行してみると:

SELECT
  value,
  MOD(value, 2) AS result
FROM (
  SELECT 3 AS value FROM dual
  UNION ALL
  SELECT NULL FROM dual
);

結果は 3 → 1NULL → NULL となります。このとき、MOD(value, 2) = 1 のようなWHERE句では、NULL行は評価対象外(FALSEでもTRUEでもない)として除外されます。

意図的にNULLを除きたい場合は、明示的に value IS NOT NULL を加えておいた方が安全です。


負の数を渡したときのMOD関数の動き

OracleのMOD関数は、負の数に対しても余りを返してくれますが、その挙動には注意が必要です。というのも、Oracleでは「被除数(第1引数)の符号をそのまま引き継ぐ」仕様になっているからです。

以下のようなSQLを試してみると:

SELECT
  value,
  MOD(value, 2) AS result
FROM (
  SELECT -3 AS value FROM dual
  UNION ALL
  SELECT -4 FROM dual
);

結果は -3 → -1-4 → 0 になります。

MOD(-3, 2)1 ではなく -1 を返す点に注意が必要です。これは他の言語(たとえばJavaやPython)と動作が異なるため、勘違いしやすいところです。

奇数・偶数の判定目的でMODを使う場合、こうした符号の違いによって「奇数とみなされない」ことを防ぐために、ABS(MOD(value, 2)) のように絶対値を取る書き方が推奨されます。こうしておくことで、値の符号に関係なく意図した結果を得ることができます。

WHERE句での具体的な使用例

続いて、WHERE句での使用例です。たとえば、奇数だけ抽出したい場合のWHERE句の書き方です。

SELECT *
FROM sample_table
WHERE MOD(value, 2) = 1;  -- 奇数のみ取得

これだけでしっかり奇数だけを絞り込むことができます。なお、MOD(value, 2) = 0 にすれば偶数になります。複数条件があるときにもシンプルに組み合わせられるのがメリットです。

SELECT文で奇数・偶数ラベルを付ける

データの一覧表示で、奇数か偶数かをラベルで見せたい場合には、CASE文を組み合わせて使うと便利です。

SELECT
  value,
  CASE
    WHEN MOD(value, 2) = 0 THEN '偶数'
    WHEN MOD(value, 2) = 1 THEN '奇数'
    ELSE '不明'
  END AS flag
FROM
  sample_table;

このように表示用のフラグをつけると、確認やデバッグにも役立ちます。ELSE句を入れておくと、NULLなど予期しない値にも対応できて安心です。


BITAND関数でも判定できる?試してわかったこと

MOD以外に、もうひとつ奇数・偶数の判定ができるのが BITAND 関数です。

これはビット演算を使ったやり方で、「早くて軽い」と言われることもあります。慣れないうちはMODの方が安心ですが、パフォーマンスが重要な処理では選択肢になるかもしれません。

なぜBITAND関数で判定できるのか

BITAND関数は、2つの整数に対してビット単位(2進数単位)でAND演算を行う関数です。
「AND演算」というのは、対応するビットが両方1だったときだけ1を返す、というものです。

「奇数と偶数の違いは、2進数で見たときの最下位ビット(1の位)に現れる」という性質があり、数値を2進数に直してみると:

  • 4 → 100 → 最下位ビットは 0 → 偶数
  • 5 → 101 → 最下位ビットは 1 → 奇数
  • 6 → 110 → 最下位ビットは 0 → 偶数
  • 7 → 111 → 最下位ビットは 1 → 奇数

つまり、その数が奇数かどうかは、最下位ビット(1の位)が1かどうかで判定できるわけです。

BITAND関数は以下のように使います。

SELECT
  value,
  BITAND(value, 1) AS bit_result -- 第二引数には1をセット(最下位ビットを見るため)
FROM
  sample_table;

この例では、BITAND(value, 1) の結果が1なら奇数、0なら偶数。MODの結果とまったく同じですが、裏側での処理は異なります。

MOD と BITAND のパフォーマンスや可読性

BITANDは処理速度の面ではMODよりわずかに優位とされることがあります。

特に、大量データをループ処理するようなバッチや分析処理で、数十万〜数百万行を対象に実行する場合には、ごく小さい差でも積もると処理時間に影響する可能性があります。

ただ、現実的な業務の中では、「そのわずかな差が本当に問題になるケース」はそう多くはありません。むしろ影響が大きいのはコードの読みやすさ・意図の伝わりやすさです。

MOD関数を使えば、「あ、これは奇数・偶数の判定だな」と一目で分かります。一方、BITANDはビット演算の知識がないと意味を取りづらく、初見の人が戸惑いやすい書き方になりがちです。

-- 可読性が高く意図が伝わる
WHERE MOD(value, 2) = 1

-- 処理は軽いが意図が読みにくい
WHERE BITAND(value, 1) = 1

結局のところ、数ミリ秒の実行時間より、数分のコード理解の遅れの方が業務への影響が大きい場面もある。そう考えると、普段はMODを使う方が無難だと感じています。


まとめ

Oracleでの奇数・偶数判定には、可読性が高く直感的なMOD関数が最適です。ただし、NULLや負数への対応、パフォーマンス面での選択肢としてBITANDも検討の余地があります。

状況に応じた最適な書き方を見つけていく過程も、業務改善のひとつとして楽しめるポイントかもしれません。

この記事を書いた人

業務システムとWebアプリの開発に20年以上携わるフリーランスエンジニア。
製造業や物流業界のシステム保守・改修を中心に、要件定義から運用改善まで幅広く対応してきました。Laravelや業務改善、AI活用など、現場で実際に試し・使い続けている技術や設計の工夫を、トラブル対応の視点も交えてブログに記録しています。

日々の業務で直面した「困ったこと」をベースに、再現性のあるノウハウをシンプルな言葉で伝えることを意識しています。

目次