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 エラーを防ぐため、すべての戻り値の型を統一することを推奨します。