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 → 1
、NULL → 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も検討の余地があります。
状況に応じた最適な書き方を見つけていく過程も、業務改善のひとつとして楽しめるポイントかもしれません。