【Oracle】DECODE関数の使い方完全解説|CASE式との違い・NULL扱い・ピボット集計まで

OracleのDECODE関数は、等値条件に基づいて値を変換するOracle独自の関数です。CASE式と同様の役割を持ちますが、構文がコンパクトで特定の場面では非常に便利です。

本記事では、基本構文から NULL の扱い・ネスト・ピボット集計への応用・CASE式との使い分けまでを完全解説します。

スポンサーリンク

DECODE関数の基本構文

SQL — DECODE関数の基本構文
DECODE(対象値,
       比較値1, 戻り値1,
       比較値2, 戻り値2,
       ...
       デフォルト値  -- 省略可。いずれにも合致しない場合の値
)
引数 説明
対象値 比較するカラムや式
比較値N 対象値と比較する値(等値比較のみ)
戻り値N 比較値Nと一致した場合に返す値
デフォルト値 どの比較値にも一致しなかった場合の値。省略時はNULLを返す

基本的な使用例

コード値を名称に変換する

SQL — 部門コードを部門名に変換
SELECT empno,
       ename,
       DECODE(deptno,
              10, '総務部',
              20, '営業部',
              30, '開発部',
              'その他') AS dept_name
  FROM emp;

フラグ値をラベルに変換する

SQL — ステータスフラグを日本語ラベルに変換
SELECT order_id,
       DECODE(status,
              '0', '未処理',
              '1', '処理中',
              '2', '完了',
              '9', 'キャンセル',
              '不明') AS status_label
  FROM orders;

NULLの扱い(重要)

DECODEは通常のSQL等値比較(=)と異なり、NULLとNULLを等しいと判断します。これはDECODE特有の挙動です。

SQL — NULLを比較値に指定する
-- manager_idがNULLの場合に「トップ」と返す
SELECT empno, ename,
       DECODE(manager_id,
              NULL, 'トップ',
              '部下あり') AS position
  FROM emp;

-- 通常のWHERE句の = 演算子ではNULL=NULLはFALSEになるが
-- DECODEではNULLをNULLとして正しく比較できる
注意: DECODE でNULLを比較値として使う際は NULL とそのまま書けます。IS NULL は不要です。ただし、CASE式では WHEN col IS NULL THEN と書く必要があります。

DECODE のネスト(入れ子)

DECODEの戻り値に別のDECODEを入れ子にすることで、複雑な条件分岐を表現できます。ただし可読性が下がるため、3段階以上のネストにはCASE式を推奨します。

SQL — DECODEのネスト例
-- 部署が10の場合、さらにジョブで分岐
SELECT ename,
       DECODE(deptno,
              10, DECODE(job,
                        'MANAGER',  '総務管理職',
                        'CLERK',    '総務一般',
                        '総務その他'),
              20, '営業部門',
              'その他部門') AS category
  FROM emp;

集計関数との組み合わせ(ピボット集計)

DECODE と SUM を組み合わせると、行データを列に展開するピボット集計(クロス集計)を実現できます。Oracle 11g以降は PIVOT 句を使う方法もありますが、古いバージョンや柔軟な集計にはDECODEが便利です。

SQL — DECODE + SUM でピボット集計(部署別給与合計)
SELECT
  job,
  SUM(DECODE(deptno, 10, sal)) AS dept10_sal,
  SUM(DECODE(deptno, 20, sal)) AS dept20_sal,
  SUM(DECODE(deptno, 30, sal)) AS dept30_sal,
  SUM(sal)                             AS total_sal
  FROM emp
 GROUP BY job
 ORDER BY job;
仕組み: DECODE(deptno, 10, sal) は部署が10ならsal値、それ以外はNULLを返します。SUMはNULLを無視するため、部署ごとの集計が列として分離されます。

ORDER BY での使用(ソート順の制御)

DECODE を ORDER BY に使うと、コードの昇順・降順とは異なる任意の順序でソートできます。

SQL — DECODEによる任意順ソート
-- status を「処理中→未処理→完了→キャンセル」の順で表示
SELECT order_id, status
  FROM orders
 ORDER BY DECODE(status,
            '1', 1,   -- 処理中を最初に
            '0', 2,   -- 未処理
            '2', 3,   -- 完了
            '9', 4,   -- キャンセルを最後に
            99);

DECODE と CASE式の比較

比較項目 DECODE CASE式
対応DB Oracle専用 標準SQL(移植性高)
比較の種類 等値比較のみ 等値・範囲・複合条件すべて可
NULL比較 NULL=NULLが真(特殊) WHEN col IS NULL と明示が必要
構文の簡潔さ 等値変換はコンパクト やや冗長だが読みやすい
推奨場面 Oracle環境での等値変換・ピボット 移植性重視・範囲条件・複雑な分岐

同じ処理をCASE式で書いた場合

SQL — DECODE と CASE式の等価比較
-- DECODE版
DECODE(deptno, 10, '総務部', 20, '営業部', 'その他')

-- CASE式版(同等の処理)
CASE deptno
  WHEN 10 THEN '総務部'
  WHEN 20 THEN '営業部'
  ELSE 'その他'
END

まとめ

用途 書き方のポイント
コード→名称変換 DECODE(col, 値1, 名称1, 値2, 名称2, デフォルト)
NULLの変換 DECODE(col, NULL, ‘NULLの場合’, ‘それ以外’)
ピボット集計 SUM(DECODE(col, 値, 集計列))
任意ソート順 ORDER BY DECODE(col, 値1, 1, 値2, 2, …)
❓ よくある質問(FAQ)  ▲ クリックで開閉

Q. DECODEはどのバージョンのOracleから使えるか?
A. 非常に古いバージョン(Oracle 6以前)から存在するOracle伝統の関数です。現在でも全バージョンで使用できますが、Oracle 8i以降はCASE式も利用可能なため、新規開発では移植性の高いCASE式を推奨します。

Q. DECODEで範囲条件(〜以上〜以下)は書けるか?
A. DECODEは等値比較のみのため、範囲条件には対応していません。範囲条件が必要な場合はCASE式の WHEN salary BETWEEN 1000 AND 2000 THEN ... を使用してください。

Q. DECODEの戻り値の型はどのように決まるか?
A. 最初の戻り値(戻り値1)のデータ型に合わせられます。その後の戻り値が異なる型の場合は暗黙的に変換されます。型の不一致による ORA-00932 エラーを防ぐため、すべての戻り値の型を統一することを推奨します。