Oracle函数(decode, sign, vnl)

目录

一、SIGN()函数

二、NVL()函数

三、DECODE()函数






一、SIGN()函数

比较大小函数SIGN()

sign(x)或者Sign(x)叫做符号函数,其功能是取某个数的符号(正或负):

当x>0,sign(x)=1;

当x=0,sign(x)=0;

当x<0, sign(x)=-1;

x可以是函数或计算表达式

二、NVL()函数

NVL函数是一个空值转换函数

NVL(表达式1,表达式2)

如果表达式1为空值,NVL返回值为表达式2的值,否则返回表达式1的值。该函数的目的是把一个空值(null)转换成一个实际的值。

其表达式的值可以是数字型、字符型和日期型。但是表达式1和表达式2的数据类型必须为同一个类型。

对数字型 NVL( comm, 0);
对字符型 NVL( TO_CHAR(comm), 'No Commission')
对日期型 NVL(hiredate,' 31-DEC-99')

例子:

select ename, NVL(TO_char(comm), ename||' is not a salesperson!') AS COMMISSION from emp;


NVL2(表达式1,表达式2,表达式3)

如果表达式1为空,返回值为表达式3的值。如果表达式1不为空,返回值为表达式2的值。

例子:

NVL2(comm,'sal+comm',sal)

NVL2函数测试comm

如果comm为空,就返回sal 的值。如果 comm 不为空(null),就返回表达式 sal+comm的值。

三、decode()函数

流程控制函数DECODE()

decode()定义

在逻辑编程中,经常用到If – Then–Else进行逻辑判断。

在DECODE的语法中,实际上就是这样的逻辑处理过程。它的语法如下:

DECODE(value, if1, then1, if2, then2, if3, then3, . . . else )

Value 代表某个表的任何类型的任意列或一个通过计算所得的任何结果。当每个value值被测试,如果value的值为if1,Decode 函数的结果是then1;如果value等于if2,Decode函数结果是then2;等等。

事实上,可以给出多个if/then配对。如果value结果不等于给出的任何配对时,Decode 结果就返回else 。 这里的if、then及else 都可以是函数或计算表达式。

decode()主要作用

将查询结果翻译成其他值(即以其他形式表现出来);

decode使用方法:

Select decode(columnname,值1,翻译值1,值2,翻译值2,...值n,翻译值n,缺省值)

From talbename

Where …

其中columnname为要选择的table中所定义的column,

含义解释:

IF 条件=值1 THEN
    
RETURN(返回值1)

ELSIF 条件=值2 THEN
    
RETURN(返回值2)  
  
......

ELSIF 条件=值n THEN 
   
RETURN(返回值n)

ELSE 
   
RETURN(缺省值)

END IF



注:其中缺省值可以是你要选择的column name 本身,也可以是你想定义的其他值,比如Other等;

decode常见用途
(1)按字段内容分组
(2)按字段内容排序
(3)固定行转列

(1) 使用DECODE实现按字段内容分组

有时候分组可能比较复杂,比如需要对某些字段内容合并分组处理,这样使用简单的GROUP BY 就不行了,但是使用CASE或DECODE就可以得到预期的结果

范例:

  • 建立简单的雇员及对应职位表
DROP TABLE t1;
CREATE TABLE
(
ID NUMBER(10),
NAME VARCHAR2(10),
JOB VARCHAR2(20)
);
INSERT INTO t1 VALUES(1,'jack','VP');
INSERT INTO t1 VALUES(2,'tony','CEO');
INSERT INTO t1 VALUES(3,'merry','VP');
INSERT INTO t1 VALUES(4,'james','OPERATION');
INSERT INTO t1 VALUES(5,'linda','OPERATION');
COMMIT;

现在需要分别统计VP及以上职位的人数、普通雇员的人数,这是使用简单的GROUP BY JOB是不行的,使用DECODE来实现就很简单


SELECT DECODE(JOB, 'VP', 'VP_CEO', 'CEO', 'VP_CEO', 'OPERATION') JOB,
COUNT(*) JOB_CNT
FROM t1
GROUP BY DECODE(JOB,'VP','VP_CEO','CEO','VP_CEO','OPERATION');

结果如下:

SQL> SELECT DECODE(JOB, 'VP', 'VP_CEO', 'CEO', 'VP_CEO', 'OPERATION') JOB,
  2  COUNT(*) JOB_CNT
  3  FROM t1
  4  GROUP BY DECODE(JOB,'VP','VP_CEO','CEO','VP_CEO','OPERATION');

JOB          JOB_CNT
--------- ----------
VP_CEO             3
OPERATION          2

(2)使用DECODE实现按字段内容排序

在日常开发中可能碰到这样的情况,比如一张表有ID,NAME字段(ID为代理主键),需要按NAME值指定排序规则(如NAME是字符型'某某部分'),那么怎样实现排序呢?

按字段内容排序和按字段内容指定动态列排序

  • 建立测试表
DROP TABLE t2;
CREATE TABLE t2
(
ID NUMBER,
DEPT_NAME VARCHAR2(10),
REGION_ID NUMBER(10)
);
INSERT INTO t2 VALUES(1,'deptA',12);
INSERT INTO t2 VALUES(2,'deptA',10);
INSERT INTO t2 VALUES(3,'deptA',9);
INSERT INTO t2 VALUES(4,'deptA',7);
INSERT INTO t2 VALUES(5,'deptB',12);
INSERT INTO t2 VALUES(6,'deptB',13);
INSERT INTO t2 VALUES(7,'deptB',22);
INSERT INTO t2 VALUES(8,'deptB',9);
INSERT INTO t2 VALUES(9,'deptC',8);
INSERT INTO t2 VALUES(10,'deptC',10);
INSERT INTO t2 VALUES(11,'deptC',11);
COMMIT;

a. 按字段内容排序

需求:按部门DEPT_NAME排序(A->B->C),对于每个部门内部按区域REGION_ID升序

分析:这里的部门DEPT_NAME不是数字(varchar2),直接排序时不行的,

如果能将DEPT_NAME的每个值转为对应的数字,再排序就可以了。

SELECT ID, DEPT_NAME, REGION_ID 
FROM t2 
ORDER BY DECODE(DEPT_NAME, 
'deptA', 1, 
'deptB', 2, 
3), 
REGION_ID;

运行结果:

SQL> SELECT ID, DEPT_NAME, REGION_ID FROM t2 ORDER BY DECODE(DEPT_NAME, 'deptA', 1, 'deptB', 2, 3), REGION_ID;

        ID DEPT_NAME   REGION_ID
---------- ---------- ----------
         4 deptA               7
         3 deptA               9
         2 deptA              10
         1 deptA              12
         8 deptB               9
         5 deptB              12
         6 deptB              13
         7 deptB              22
         9 deptC               8
        10 deptC              10
        11 deptC              11

已选择11行。

b. 按字段内容指定动态列排序

需求:若DEPT_NAME为deptA,则按ID升序排列,否则按REGION_ID升序排序

SELECT ID, DEPT_NAME, REGION_ID 
FROM t2 
ORDER BY DECODE(DEPT_NAME,
'deptA',ID, 
REGION_ID);

(3) 使用DECODE实现固定行转列

TODO 下面代码实践!

  • 简单的员工工作统计表
DROP TABLE t3; 

CREATE TABLE t3( 
STUDENT_NO NUMBER(10), 
STUDENT_NAME VARCHAR2(10), 
COURSE_TYPE VARCHAR2(10), 
COURSE_SCORE NUMBER(10) 
);

INSERT INTO t3 VALUES(1,'jack','english',80);
INSERT INTO t3 VALUES(1,'jack','chinese',90);
INSERT INTO t3 VALUES(1,'jack','math',85);
INSERT INTO t3 VALUES(2,'tony','english',70);
INSERT INTO t3 VALUES(2,'tony','chinese',95);
INSERT INTO t3 VALUES(2,'tony','math',80);
COMMIT;

实现行转列:

SELECT STUDENT_NAME, DECODE(COURSE_TYPE, 'english', COURSE_SCORE) FROM t3;

运行结果:


SQL> SELECT STUDENT_NAME, DECODE(COURSE_TYPE, 'english', COURSE_SCORE) FROM t3;

STUDENT_NA DECODE(COURSE_TYPE,'ENGLISH',COURSE_SCORE)
---------- ------------------------------------------
jack                                               80
jack
jack
tony                                               70
tony
tony

已选择6行。

对比:

SQL> select * from t3;

STUDENT_NO STUDENT_NA COURSE_TYP COURSE_SCORE
---------- ---------- ---------- ------------
         1 jack       english              80
         1 jack       chinese              90
         1 jack       math                 85
         2 tony       english              70
         2 tony       chinese              95
         2 tony       math                 80

已选择6行。
分析这条语句,分组与不分组的差别在哪里?
SELECT STUDENT_NAME,
MAX(DECODE(COURSE_TYPE,'english',COURSE_SCORE)) ENGLISH,
MAX(DECODE(COURSE_TYPE,'chinese',COURSE_SCORE)) CHINESE,
MAX(DECODE(COURSE_TYPE,'math',COURSE_SCORE)) MATH
FROM t3
GROUP BY STUDENT_NAME;



为什么需要MAX?

因为要实现行转列,按字段分组,对DECODE中的非分组列必须要有分组函数,当然MIN、SUM
AVG等组函数也可以实现,MAX、MIN对任何类型都适用,SUM、AVG只能对数值型;

你可能感兴趣的:(Oracle函数(decode, sign, vnl))