目录
一、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只能对数值型;