SQLのNVL2関数についてまとめています。
NVL2はOracleのNULL比較関数 NULLの場合にNULL以外を返り値として返すことが可能
まずはnvlの実行結果を見てみましょう。第一引数がNULLなら第二引数を、NULL以外なら第一引数を返します。
select nvl(NULL,1) from dual; NVL(NULL,1) ----- 1 select nvl(2,1) from dual; NVL(2,1) ----- 2
NVL2は、指定した値がNULLだった場合とNULL以外の場合で返す値を変えることができる関数です。第一引数がNULL以外なら第二引数を、NULLなら第三引数を返します。
select nvl2(NULL,1,2) from dual; NVL2(NULL,1,2) ----- 2 select nvl2(1,1,2) from dual; NVL2(1,1,2) ----- 1
NVL2はCASE式で置き換えが可能
NVL2はOracleの独自拡張です。MySQLなど他のRDBMSに移植する場合は、CASE式で置き換えが可能です。
//NVL()をcase式で置き換えた例 SELECT CASE WHEN num IS NULL THEN 0 ELSE str END FROM emp; //NVL2()をcase式で置き換えた例 SELECT CASE WHEN num IS NULL THEN 0 ELSE num * 2 END FROM emp
NVL2は比較値以外の値を返すことが可能
以下のSQLは、データベースHR.employeesからmanager_idがNULLの場合は1を、NULL以外なら0を取得しています。
select employee_ID, first_name, last_name, nvl2(manager_id, 0, 1) from HR.employees; EMPLOYEE_ID FIRST_NAME LAST_NAME NVL2(MANAGER_ID,0,1) ---------------------------- 100 Steven King 1 101 Neena Kochhar 0 102 Lex De Haan 0 103 Alexander Hunold 0 104 Bruce Ernst 0 105 David Austin 0 106 Valli Pataballa 0 107 Diana Lorentz 0 108 Nancy Greenberg 0 109 Daniel Faviet 0 110 John Chen 0 : :
outer joinの場合対応する値がなくてNULL値になっているカラムを置き換えるには、以下の様にします。以下は、manager_idがNULLの場合はN/A、NULL以外の場合はavailableを返すサンプルです。
select a.empno, a.deptno, a.ename, a.job, nvl2(b.deptno, 'available', 'N/A') from SCOTT.emp a, SCOTT.dept b where a.deptno = b.deptno (+); EMPNO DEPTNO ENAME JOB NVL2(B.DEPTNO,'AVAILABLE','N/A') 7001 99 TARO OBSERVER N/A 7839 10 KING PRESIDENT available 7698 30 BLAKE MANAGER available 7782 10 CLARK MANAGER available 7566 20 JONES MANAGER available 7788 20 SCOTT ANALYST available 7902 20 FORD ANALYST available 7369 20 SMITH CLERK available 7499 30 ALLEN SALESMAN available 7521 30 WARD SALESMAN available 7654 30 MARTIN SALESMAN available : :
outer join先のSCOTT.deptテーブルのdeptnoがNULLの場合はN/Aを、NULL以外の場合はavailableを取得します。
NVL2とCOALESCEの違い COALSCEは複数の引数指定が可能
Oracleでは、NVL2の代わりにcoalesce関数を使うことも可能です。COALSCEは複数の引数を指定することができ、引数1がNULLだったら引数2を比較、引数2がNULLだったら、引数3を比較…と指定した引数を順番にNULL比較していきます。
比較した結果、NULL以外が現れた場合はその値を、全てNULLだった場合はNULLを返します。
SELECT COALESCE(NULL,1) from dual; COALESCE(NULL,1) ---------- 1 SELECT COALESCE(NULL,NULL,NULL) from dual; COALESCE(NULL,NULL,NULL) ---------- - SELECT COALESCE(NULL,NULL,NULL,99) from dual; COALESCE(NULL,NULL,NULL,99) ---------- 99
NVL2の場合は、比較する値は一つであることと、比較した値以外を返すことができる点が異なります。NVL、NVL2はOracleの独自関数ですが、COALSCEはMySQLなどの他のデータベース管理システムでも利用可能です。
下記のSQLは、年ごとの社員の年収を集計するSQLです。年収がNULLの場合はCOALESCEで0に置き換えています。
select Date_format(birth_date, '%Y') as year, Sum(COALESCE(salary,0)) from employees inner join salaries on salaries.emp_no = employees.emp_no inner join dept_emp on employees.emp_no = dept_emp.emp_no inner join departments on dept_emp.dept_no = departments.dept_no where salaries.to_date = '9999-01-01' and dept_name = 'Sales' group by Date_format(birth_date, '%Y') +------+-------------------------+ | year | Sum(COALESCE(salary,0)) | +------+-------------------------+ | 1952 | 266268511 | | 1953 | 279889946 | | 1954 | 284458184 | | 1955 | 292812067 | | 1956 | 288620912 | | 1957 | 284076293 | | 1958 | 294605154 | | 1959 | 289944673 | | 1960 | 281743172 | | 1961 | 282715210 | | 1962 | 290871654 | | 1963 | 289909858 | | 1964 | 281566480 | | 1965 | 23888563 | +------+-------------------------+ 14 rows in set (0.73 sec)
【関連記事】
▶SQL coalesce 値がNULLの場合の代替値を返す 簡易版のNVLやNULLIFが使えるDBもあり
まとめ
- NVL2は、NULL比較してNULL以外の値を返すOracle独自の関数
- 他のRDBMSでは、CASE文で置き換えが可能
- NULL比較をおこなうCOALSCEとは指定できる引数の数と任意の値を返せる点が異なる