1 函数
1.作用
- 对数据进行计算
- 修改单个数据项
- 操作行组的输出
- 格式化显示日期和数字
- 转换列数据类型
2.类型
- 单行函数只对单个行进行操作,每行返回一个结果
- 多行函数可以操作行组来为每组行提供一个结果
2 单行函数
单行函数用于描述SQL中不同类型的函数,在SELECT语句中使用字符,数字和日期函数。
1.作用
- 操作数据对象
- 接受函数返回一个结果
- 只对一行进行变换
- 每行返回一个结果
- 可以转换数据类型
- 可以嵌套
- 参数可以是列、值或表达式
单行函数用于操作数据项。它们接受一个或多个参数,并为查询返回的每一行返回一个值,可以是:用户提供的值、变量值、列名或表达式。
2.特点
- 对查询中返回的每一行执行操作
- 每行返回一个结果
- 可能返回引用的数据类型不同的数据值
- 可能需要一个或多个参数
- 可用于select,where,order by子句;可以嵌套
3.类型 - 字符函数
接受字符输入,可以同时返回字符值和数字值 - 数字函数
接受数字输入并返回数值 - 日期函数
操作日期数据类型的值(所有日期函数返回的值为日期数据类型,但months_between除外,它返回一个数字) - 转换
- 通用
4.dual表
-
DUAL表是一个“伪表”(虚拟表),只包含一个列DUMMY,数据类型为VARCHAR2(1)。表只包含一行,其DUMMY列的值为X。
-
DUAL表是为了语法上的完整性。
-
可以用来当计算器、返回日期等测试函数和表达式
SQL> select * from dual;
D
-
X
SQL> select 123*4 from dual;
123*4
----------
492
SQL> select sysdate from dual;
SYSDATE
---------
14-MAY-19
2.1 字符函数
大小写转换函数 | 字符处理函数 |
---|---|
LOWER、UPPER、INITCAP | CONCAT、SUBSTR、LENGTH、INSTR、LPAD/RPAD、TRIM、REPLACE |
2.1.1 CONCAT()
链接字符串、列、表达式
- 将good和dba连接
SQL> select concat('good','dba') from dual;
CONCAT(
-------
gooddba
- 通过连接符连接
SQL> select ename||' is a '||job from emp;
ENAME||'ISA'||JOB
-------------------------
SMITH is a CLERK
ALLEN is a SALESMAN
WARD is a SALESMAN
JONES is a MANAGER
MARTIN is a SALESMAN
BLAKE is a MANAGER
CLARK is a MANAGER
SCOTT is a ANALYST
KING is a PRESIDENT
TURNER is a SALESMAN
ADAMS is a CLERK
JAMES is a CLERK
FORD is a ANALYST
MILLER is a CLERK
14 rows selected.
- 通过concat连接
SQL> select concat(concat(ename,' is '),job) a
2 from emp;
A
-----------------------
SMITH is CLERK
ALLEN is SALESMAN
WARD is SALESMAN
JONES is MANAGER
MARTIN is SALESMAN
BLAKE is MANAGER
CLARK is MANAGER
SCOTT is ANALYST
KING is PRESIDENT
TURNER is SALESMAN
ADAMS is CLERK
JAMES is CLERK
FORD is ANALYST
MILLER is CLERK
14 rows selected.
2.1.2 SUBSTR()
截取字符串
- 截取第一个字符开始的3个字符
SQL> select substr('oracle',1,3) from dual;
SUB
---
ora
- 截取倒数第二个字符开始的2个字符
SQL> select substr('oracle',-2,2) from dual;
SU
--
le
- 取第四个字符开始到最后的所有字符
SQL> select substr('oracle',4) from dual;
SUB
---
cle
- 取倒数第五个字符到最后的所有字符
SQL> select substr('oracle',-5) from dual;
SUBST
-----
racle
2.1.3 length()
获取字符数
SQL> select length('oracle') from dual;
LENGTH('ORACLE')
----------------
6
2.1.4 instr()
- 后面字符串在前面字符串第一次出现的位置
SQL> select instr('oracle','cle') from dual;
INSTR('ORACLE','CLE')
---------------------
4
instr经常用来做判断,判断一个字符串是否在另外一个字符串中
- 使用字符控制函数:查询名字里有A的名字
SQL> select ename,instr(ename,'A') from emp;
ENAME INSTR(ENAME,'A')
---------- ----------------
SMITH 0
ALLEN 1
WARD 2
JONES 0
MARTIN 2
BLAKE 3
CLARK 3
SCOTT 0
KING 0
TURNER 0
ADAMS 1
JAMES 2
FORD 0
MILLER 0
14 rows selected.
- 查询从第 3 个字符开始,*第 4 次出现的位置
SQL> select instr('1*2*3*4*5*','*',3,4) from dual;
INSTR('1*2*3*4*5*','*',3,4)
---------------------------
10
- 查询从倒数第 3 个字符开始向前,*第 2 次出现的位置
SQL> select instr('1*2*3*4*5*','*',-3,2) from dual;
INSTR('1*2*3*4*5*','*',-3,2)
----------------------------
6
2.1.5 RPAD()右补全
SQL> select ename,sal,rpad(sal,5,'*') from emp;
ENAME SAL RPAD(SAL,5,'*')
---------- ---------- --------------------
SMITH 800 800**
ALLEN 1600 1600*
WARD 1250 1250*
JONES 2975 2975*
MARTIN 1250 1250*
BLAKE 2850 2850*
CLARK 2450 2450*
SCOTT 3000 3000*
KING 5000 5000*
TURNER 1500 1500*
ADAMS 1100 1100*
JAMES 950 950**
FORD 3000 3000*
MILLER 1300 1300*
14 rows selected.
2.1.6 LPAD()左补全
SQL> select sal,lpad(sal,4,0),rpad(sal,4,0) from emp;
SAL LPAD(SAL,4,0) RPAD(SAL,4,0)
---------- ---------------- ----------------
800 0800 8000
1600 1600 1600
1250 1250 1250
2975 2975 2975
1250 1250 1250
2850 2850 2850
2450 2450 2450
3000 3000 3000
5000 5000 5000
1500 1500 1500
1100 1100 1100
950 0950 9500
3000 3000 3000
1300 1300 1300
14 rows selected.
2.1.7 TRIM()
去掉前后空格,或者从后面串首尾去掉前面字符:
SQL> select trim(' hello ') from dual;
TRIM(
-----
hello
SQL> select length(' hello '),length(trim(' hello ')) from dual;
LENGTH('HELLO') LENGTH(TRIM('HELLO'))
--------------- ---------------------
7 5
2.2 数值函数
2.2.1 ROUND()
四舍五入到指定的十进制值
SQL> select round(45.368,0) from dual;
ROUND(45.368,0)
---------------
45
SQL> select round(45.237,-1) from dual;
ROUND(45.237,-1)
----------------
50
SQL> select round(45.932,2) from dual;
ROUND(45.932,2)
---------------
45.93
SQL> select round(45.677,2) from dual;
ROUND(45.677,2)
---------------
45.68
2.2.2 TRUNC()
截断到指定十进制值
SQL> select trunc(45.675,2) from dual;
TRUNC(45.675,2)
---------------
45.67
SQL> select trunc(45.677,2) from dual;
TRUNC(45.677,2)
---------------
45.67
2.2.3 MOD()
返回余数
SQL> select mod(1600,300) from dual;
MOD(1600,300)
-------------
100
2.3 使用日期
Oracle内部使用数字存储日期:世纪、年、月、日、小时
默认日期格式:DD-MON-RR
2.3.1 SYSDATE()
SYSDATE是一个日期函数,返回当前数据库服务器的日期和时间。可以像使用任何其他列名一样使用SYSDATE。
SQL> select sysdate from dual;
SYSDATE
---------
14-MAY-19
修改当前session日期格式
SQL> alter session set nls_date_format = 'yyyy-mm-dd hh24:mi:ss day';
Session altered.
SQL> select sysdate from dual;
SYSDATE
-----------------------------
2019-05-14 15:10:57 tuesday
SQL> select hiredate from emp;
HIREDATE
-----------------------------
1980-12-17 00:00:00 wednesday
1981-02-20 00:00:00 friday
1981-02-22 00:00:00 sunday
1981-04-02 00:00:00 thursday
1981-09-28 00:00:00 monday
1981-05-01 00:00:00 friday
1981-06-09 00:00:00 tuesday
1987-04-19 00:00:00 sunday
1981-11-17 00:00:00 tuesday
1981-09-08 00:00:00 tuesday
1987-05-23 00:00:00 saturday
1981-12-03 00:00:00 thursday
1981-12-03 00:00:00 thursday
1982-01-23 00:00:00 saturday
14 rows selected.
2.3.2 日期的算术运算
计算方法 | 计算公式 |
---|---|
date+number | 加几天(结果还是日期) |
date-number | 减几天 |
date-date | 两个日期相减返回日期之间的相差天数 |
date+number/24 | 加小时到日期上 |
因为数据库将日期存储为数字,所以可以使用加减法等算术运算符执行计算。
- 一天以后
SQL> alter session set nls_date_format = 'DD-MON-RR';
Session altered.
SQL> select sysdate from dual;
SYSDATE
---------
14-MAY-19
SQL> select sysdate + 1 from dual;
SYSDATE+1
---------
15-MAY-19
- 日期相减计算入职多少年
SQL> select ename,hiredate,round((sysdate-hiredate)/365,0) years from emp;
ENAME HIREDATE YEARS
---------- --------- ----------
SMITH 17-DEC-80 38
ALLEN 20-FEB-81 38
WARD 22-FEB-81 38
JONES 02-APR-81 38
MARTIN 28-SEP-81 38
BLAKE 01-MAY-81 38
CLARK 09-JUN-81 38
SCOTT 19-APR-87 32
KING 17-NOV-81 38
TURNER 08-SEP-81 38
ADAMS 23-MAY-87 32
JAMES 03-DEC-81 37
FORD 03-DEC-81 37
MILLER 23-JAN-82 37
14 rows selected.
- 一小时后
SQL> alter session set nls_date_format = 'yyyy-mm-dd hh24:mi:ss day';
Session altered.
SQL> select sysdate +1/24 from dual;
SYSDATE+1/24
-----------------------------
2019-05-14 16:18:34 tuesday
- 一分钟后
SQL> alter session set nls_date_format = 'yyyy-mm-dd hh24:mi:ss day';
Session altered.
SQL> select sysdate +1/24 from dual;
SYSDATE+1/24
-----------------------------
2019-05-14 16:18:34 tuesday
2.3.3 months_between()
两个日期相差的月数
SQL> select empno,ename,months_between(sysdate,hiredate) months from emp;
EMPNO ENAME MONTHS
---------- ---------- ----------
7369 SMITH 460.923843
7499 ALLEN 458.827069
7521 WARD 458.762553
7566 JONES 457.407714
7654 MARTIN 451.569004
7698 BLAKE 456.439972
7782 CLARK 455.181907
7788 SCOTT 384.859327
7839 KING 449.923843
7844 TURNER 452.214166
7876 ADAMS 383.730295
7900 JAMES 449.375456
7902 FORD 449.375456
7934 MILLER 447.730295
14 rows selected.
2.3.4 ADD_MONTHS()
向指定日期中加上若干月数
- 日期增加月份,一年前:
SQL> select sysdate,add_months(sysdate,-12) from dual;
SYSDATE ADD_MONTHS(SYSDATE,-12)
----------------------------- -----------------------------
2019-05-14 15:20:53 tuesday 2018-05-14 15:20:53 monday
只有增加月的函数,没有增加年和日的函数
2.3.5 LAST_DAY()
显示本月的最后一天
SQL> select sysdate,last_day(sysdate) from dual;
SYSDATE LAST_DAY(SYSDATE)
----------------------------- -----------------------------
2019-05-14 15:21:25 tuesday 2019-05-31 15:21:25 friday
2.3.6 NEXT_DAY()
下一个
SQL> select next_day(sysdate,'MONDAY') from dual;
NEXT_DAY(SYSDATE,'MONDAY')
-----------------------------
2019-05-20 15:22:00 monday
SQL> select next_day(sysdate,2) from dual;
NEXT_DAY(SYSDATE,2)
-----------------------------
2019-05-20 15:22:38 monday
2.3.7 ROUND()
日期四舍五入
SQL> select sysdate,round(sysdate) from dual;
SYSDATE ROUND(SYSDATE)
----------------------------- -----------------------------
2019-05-14 15:23:01 tuesday 2019-05-15 00:00:00 wednesday
SQL> select sysdate,round(sysdate,'mi') from dual;
SYSDATE ROUND(SYSDATE,'MI')
----------------------------- -----------------------------
2019-05-14 15:26:57 tuesday 2019-05-14 15:27:00 tuesday
SQL> select sysdate,round(sysdate,'DD') from dual;
SYSDATE ROUND(SYSDATE,'DD')
----------------------------- -----------------------------
2019-05-14 15:27:32 tuesday 2019-05-15 00:00:00 wednesday
2.3.8 TRUNC()
日期截断
- 今年第一天
SQL> select sysdate,trunc(sysdate,'yyyy') from dual;
SYSDATE TRUNC(SYSDATE,'YYYY')
----------------------------- -----------------------------
2019-05-14 15:29:11 tuesday 2019-01-01 00:00:00 tuesday
3 转换函数
3.1 隐式和显式数据类型转换
- 隐式数据类型转换:在后台转换
- 显式数据类型转换:数据类型与默认格式匹配
3.2 隐式数据类型转换
- Oracle服务器自动完成下列转换
From | To |
---|---|
VARCHAR2 or CHAR | NUMBER |
VARCHAR2 or CHAR | DATE |
Oracle服务器可以在表达式中自动执行数据类型转换。
如,hiredate>‘01-JAN-90’会导致从字符串‘01-JAN-90’到日期的隐式转换。
所以可以隐式地将VARCHAR2或CHAR值转换为表达式中的数字或日期数字类型。
-
char和varchar的区别
char 长度固定
varchar2 长度动态变化,先判断,再分配,再看超没超过长度 -
Oracle服务器自动完成下列转换
From | To |
---|---|
NUMBER | VARCHAR2 or CHAR |
DATE | VARCHAR2 or CHAR |
通常,当需要数据类型转换时,Oracle服务器使用表达式规则。
如,grade列是CHAR(2)类型。表达式grade = 2 将导致数值2隐式转换为字符串”2“
3.3 显式数据类型转换
3.4 TO_CHAR函数对日期的转换
TO_CHAR将datetime数据类型转换为format_model指定格式的VARCHAR2数据类型值。
格式模式是描述存储在字符串中的datetime格式的字符文字。
可以使用TO_CHAR函数将日期从其默认格式转换为指定格式。
- 格式:TO_CHAR(date,‘format_model’)
1.必须包含在单引号内
2.大小写敏感
3.可以包含任意的有效日期格式
4.可以使用fm去掉多余的空格或者前导零
5.与日期值用逗号隔开
SQL> select ename,to_char(hiredate,'MM/YY') MON from emp;
ENAME MON
---------- -----
SMITH 12/80
ALLEN 02/81
WARD 02/81
JONES 04/81
MARTIN 09/81
BLAKE 05/81
CLARK 06/81
SCOTT 04/87
KING 11/81
TURNER 09/81
ADAMS 05/87
JAMES 12/81
FORD 12/81
MILLER 01/82
14 rows selected.
YYYY 完整的年份
YEAR 年(英文)
MM 双位数字月份
MONTH 完整的月份名称
MON 月份的三个字母缩写
DY 星期的三个字母缩写
DAY 完整的星期名称
DD 月份的数字(天)
HH24:MI:SS AM 15:45:32 PM
DD “of” MONTH 12 of OCTOBER
ddspth 日期在月份中的位置(如fourteenth)
3.5 TO_CHAR函数对数字的转换
- 格式:TO_CHAR(number,‘format_model’)
9 代表一个数字
0 强制显示0
$ 放置一个浮动的美元符号
L 采用浮动本地货币符号
. 打印小数点
, 打印一个逗号作为千位标识符
SQL> select sal,to_char(sal,'$999,999,999.90') s from emp;
SAL S
---------- ----------------
800 $800.00
1600 $1,600.00
1250 $1,250.00
2975 $2,975.00
1250 $1,250.00
2850 $2,850.00
2450 $2,450.00
3000 $3,000.00
5000 $5,000.00
1500 $1,500.00
1100 $1,100.00
950 $950.00
3000 $3,000.00
1300 $1,300.00
14 rows selected.
这里,第一列是数字类型,第二列是字符类型
- 如果位数不够,会显示遗传数字符号####代替,而不是数字超过格式模型中提供的数字的整数
SQL> select sal,to_char(sal,'$999') s from emp;
SAL S
---------- -----
800 $800
1600 #####
1250 #####
2975 #####
1250 #####
2850 #####
2450 #####
3000 #####
5000 #####
1500 #####
1100 #####
950 $950
3000 #####
1300 #####
14 rows selected.
如果在format model里面添加G、D等,是无效的数字默认类型
- Oracle服务器将存储的decimal值四舍五入到格式模型中提供的小数位数
3.6 TO_NUMBER和TO_DATE
- 使用TO_NUMBER函数将字符转换为数字格式:
TO_NUMBER(char[,'format_model])
- 使用TO_DATE函数将字符转换为日期格式:
TO_DATE(char[,'format_model'])
- 字符参数中的标点符号和引号必须与格式模型的相应部分完全匹配(大小写除外)
- 字符参数不能有额外的空格
- 字符参数中的数字数据必须与格式模式中的相应元素具有相同的位数。
3.7 嵌套函数
- 单行函数可以嵌套到任意层数
- 嵌套函数的执行顺序是由内至外
3.8 通用函数
这些函数适用于任何数据类型,同时也适用于空值
3.8.1 NVL()
NVL (expr1,expr2)
转换null值为实际的数值
SQL> select nvl2(comm,0,1000),comm from emp;
NVL2(COMM,0,1000) COMM
----------------- ----------
1000
0 300
0 500
1000
0 1400
1000
1000
1000
1000
0 0
1000
1000
1000
1000
14 rows selected.
3.8.2 NVL2()
NVL2 (expr1,expr2,expr3)
如果expr1不是null,转换为expr2,如果expr1是空值,则转换为expr3
# 可以输出字符串
SQL> select ename,sal,nvl2(comm,'sal+comm','sal') income from emp;
ENAME SAL INCOME
---------- ---------- --------
SMITH 800 sal
ALLEN 1600 sal+comm
WARD 1250 sal+comm
JONES 2975 sal
MARTIN 1250 sal+comm
BLAKE 2850 sal
CLARK 2450 sal
SCOTT 3000 sal
KING 5000 sal
TURNER 1500 sal+comm
ADAMS 1100 sal
JAMES 950 sal
FORD 3000 sal
MILLER 1300 sal
14 rows selected.
# 计算收入
SQL> select ename,sal,comm,nvl2(comm,comm+sal,sal) income from emp;
ENAME SAL COMM INCOME
---------- ---------- ---------- ----------
SMITH 800 800
ALLEN 1600 300 1900
WARD 1250 500 1750
JONES 2975 2975
MARTIN 1250 1400 2650
BLAKE 2850 2850
CLARK 2450 2450
SCOTT 3000 3000
KING 5000 5000
TURNER 1500 0 1500
ADAMS 1100 1100
JAMES 950 950
FORD 3000 3000
MILLER 1300 1300
14 rows selected.
3.8.3 NULLIF()
NULLIF(expr1,expr2)
比较两个表达式,如果它们相等,返回null;如果它们不相等,返回第一个表达式
SQL> select ename,job,length(ename) l1,length(job) l2,
2 nullif(length(ename),length(job)) l
3 from emp;
ENAME JOB L1 L2 L
---------- --------- ---------- ---------- ----------
SMITH CLERK 5 5
ALLEN SALESMAN 5 8 5
WARD SALESMAN 4 8 4
JONES MANAGER 5 7 5
MARTIN SALESMAN 6 8 6
BLAKE MANAGER 5 7 5
CLARK MANAGER 5 7 5
SCOTT ANALYST 5 7 5
KING PRESIDENT 4 9 4
TURNER SALESMAN 6 8 6
ADAMS CLERK 5 5
JAMES CLERK 5 5
FORD ANALYST 4 7 4
MILLER CLERK 6 5 6
14 rows selected.
3.8.4 COALESCE()
COALESCE(expr1,expr2,...,exprn)
返回表达式列表中的第一个非空表达式
COALESCE与NVL相比的优点在于COALESCE可以同时处理交替的多个值。如果第一个表达式非空,则返回这个表达式,对其他的参数进行COALESCE。
SQL> select ename,empno,mgr,comm,
2 coalesce(to_char(comm),to_char(mgr),'No commission and no manager') a
3 from emp;
ENAME EMPNO MGR COMM A
---------- ---------- ---------- ---------- ----------------------------------------
SMITH 7369 7902 7902
ALLEN 7499 7698 300 300
WARD 7521 7698 500 500
JONES 7566 7839 7839
MARTIN 7654 7698 1400 1400
BLAKE 7698 7839 7839
CLARK 7782 7839 7839
SCOTT 7788 7566 7566
KING 7839 No commission and no manager
TURNER 7844 7698 0 0
ADAMS 7876 7788 7788
JAMES 7900 7698 7698
FORD 7902 7566 7566
MILLER 7934 7782 7782
14 rows selected.
如果mgr值不是null,就会显示它,如果mgr值为null,则会显示comm。
如果mgr和comm都为null,则显示“没有佣金,就没有经理”
应用to_char函数时,所有表达式应具有相同的数据类型
4 条件表达式
在SQL语句中使用IF-THEN-ELSE逻辑,可以使用CASE表达式和DECODE函数。
4.1 CASE表达式
- 语法
CASE expr WHEN comparision_expr1 THEN return_expr1
[WHEN comparision_expr2 THEN return_expr2
WHEN comparision_expr3 THEN return_expr3
ELSE else_expr]
END
例:
SQL> select ename,job,sal,
2 case job when 'ANALYST' then 1.5*12*sal
3 when 'SALESMAN' then 1.4*12*sal
4 when 'MANAGER' then 1.3*12*sal
5 else sal end "REVISED_SAL"
6 from emp;
ENAME JOB SAL REVISED_SAL
---------- --------- ---------- -----------
SMITH CLERK 800 800
ALLEN SALESMAN 1600 26880
WARD SALESMAN 1250 21000
JONES MANAGER 2975 46410
MARTIN SALESMAN 1250 21000
BLAKE MANAGER 2850 44460
CLARK MANAGER 2450 38220
SCOTT ANALYST 3000 54000
KING PRESIDENT 5000 5000
TURNER SALESMAN 1500 25200
ADAMS CLERK 1100 1100
JAMES CLERK 950 950
FORD ANALYST 3000 54000
MILLER CLERK 1300 1300
14 rows selected.
SQL> select ename,job,sal,12*sal yesa,
2 case when job in('MANAGER','ANALYST') then 1.5*12*sal
3 when job = 'SALESMAN' then 1.2*12*sal
4 else 12*sal end "NEW"
5 from emp;
ENAME JOB SAL YESA NEW
---------- --------- ---------- ---------- ----------
SMITH CLERK 800 9600 9600
ALLEN SALESMAN 1600 19200 23040
WARD SALESMAN 1250 15000 18000
JONES MANAGER 2975 35700 53550
MARTIN SALESMAN 1250 15000 18000
BLAKE MANAGER 2850 34200 51300
CLARK MANAGER 2450 29400 44100
SCOTT ANALYST 3000 36000 54000
KING PRESIDENT 5000 60000 60000
TURNER SALESMAN 1500 18000 21600
ADAMS CLERK 1100 13200 13200
JAMES CLERK 950 11400 11400
FORD ANALYST 3000 36000 54000
MILLER CLERK 1300 15600 15600
14 rows selected.
SQL> select ename,job,sal,nvl(comm,0),
2 case when (sal+nvl(comm,0)) between 1000 and 1500 then 'BAD'
3 when (sal+nvl(comm,0)) between 1500 and 4000 then 'GOOD'
4 when (sal+nvl(comm,0)) >4000 then 'VERY GOOD'
5 else 'NULL' end "GRADE"
6 from emp;
ENAME JOB SAL NVL(COMM,0) GRADE
---------- --------- ---------- ----------- ---------
SMITH CLERK 800 0 NULL
ALLEN SALESMAN 1600 300 GOOD
WARD SALESMAN 1250 500 GOOD
JONES MANAGER 2975 0 GOOD
MARTIN SALESMAN 1250 1400 GOOD
BLAKE MANAGER 2850 0 GOOD
CLARK MANAGER 2450 0 GOOD
SCOTT ANALYST 3000 0 GOOD
KING PRESIDENT 5000 0 VERY GOOD
TURNER SALESMAN 1500 0 BAD
ADAMS CLERK 1100 0 BAD
JAMES CLERK 950 0 NULL
FORD ANALYST 3000 0 GOOD
MILLER CLERK 1300 0 BAD
14 rows selected.
4.2 DECODE函数
- 语法
DECODE(col|expression,search1,result1
[ , search2,result2, ... , ]
[ , default])
DECODE函数对表达式的解码方式类似于各种语言中使用的IF-THEN-ELSE逻辑。
DECODE函数将表达式与每个搜索值进行比较后对其进行解码。
如果表达式与搜索相同,则返回结果。
如果省略默认值,则返回空值,搜索结果的值不匹配任何值。
SQL> select ename,job,sal,
2 decode (job,'ANALYST',1.2*SAL,
3 'MANAGER',1.4*SAL,
4 'SALESMAN',3*SAL,
5 SAL)
6 REVISED_SALARY
7 from emp;
ENAME JOB SAL REVISED_SALARY
---------- --------- ---------- --------------
SMITH CLERK 800 800
ALLEN SALESMAN 1600 4800
WARD SALESMAN 1250 3750
JONES MANAGER 2975 4165
MARTIN SALESMAN 1250 3750
BLAKE MANAGER 2850 3990
CLARK MANAGER 2450 3430
SCOTT ANALYST 3000 3600
KING PRESIDENT 5000 5000
TURNER SALESMAN 1500 4500
ADAMS CLERK 1100 1100
JAMES CLERK 950 950
FORD ANALYST 3000 3600
MILLER CLERK 1300 1300
14 rows selected.
显示部门20的员工,适用的税率:
SQL> select ename,sal,
2 decode(trunc(sal/2000,0),
3 0,'0.00',
4 1,'0.09',
5 2,'0.20',
6 3,'0.30',
7 4,'0.40',
8 5,'0.42',
9 6,'0.44',
10 '0.45') TAX_RATE
11 from emp
12 where deptno = 20;
ENAME SAL TAX_
---------- ---------- ----
SMITH 800 0.00
JONES 2975 0.09
SCOTT 3000 0.09
ADAMS 1100 0.00
FORD 3000 0.09
5 使用组/分组函数汇总数据
5.1 分组函数
- 分组函数作用于一组数据,并对一组数据返回一个值。
- 语法
SELECT group_function(column) , ...
FROM table
[WHERE condition]
[ORDER BY column];
5.1.1 AVG()
平均
5.1.2 SUM()
求和
SQL> select avg(sal),sum(sal),max(sal),min(sal) from emp;
AVG(SAL) SUM(SAL) MAX(SAL) MIN(SAL)
---------- ---------- ---------- ----------
2073.21429 29025 5000 800
5.1.3 MAX()/MIN()
可以对数字、字符和日期数据类型使用MAX和MIN函数
SQL> select avg(ename) from emp;
select avg(ename) from emp
*
ERROR at line 1:
ORA-01722: invalid number
SQL> select avg(hiredate) from emp;
select avg(hiredate) from emp
*
ERROR at line 1:
ORA-00932: inconsistent datatypes: expected NUMBER got DATE
SQL> select min(hiredate),max(ename) from emp;
MIN(HIRED MAX(ENAME)
--------- ----------
17-DEC-80 WARD
5.1.4 COUNT()统计值
1)count(*)
返回满足select语句条件的表中的行数,包括重复的行和任何列中包含空值的行。如果select语句中包含where子句,count(*)返回满足where子句中条件的行数。
SQL> select count(*) from emp
2 where deptno = 20;
COUNT(*)
----------
5
count(1)与count(*) 的效果一样的,并添加一列值为1的列
SQL> select count(*) from emp;
COUNT(*)
----------
14
SQL> select count(1) from emp;
COUNT(1)
----------
14
2)count(expr)
返回非空值的expr的行数
SQL> select count(comm) from emp;
COUNT(COMM)
-----------
4
3)count(distinct expr)
返回expr非空且不重复的记录数
SQL> select count(distinct job) from emp;
COUNT(DISTINCTJOB)
------------------
5
5.1.5 STDDEV()标准差
5.1.6 VARIANCE()方差
5.2 分组函数与空值
- 组函数忽略空值
SQL> select avg(comm) from emp;
AVG(COMM)
----------
550
- NVL函数使分组函数不忽略空值
SQL> select avg(nvl(comm,0)) from emp;
AVG(NVL(COMM,0))
----------------
157.142857
6 GROUP BY子句
- 将信息分成更小的组
- 语法:
SELECT column,group_function(column)
FROM table
GROUP BY group_by_expression;
- 使用group by子句将表中的数据分成若干组。
SQL> select deptno,avg(sal) from emp
2 group by deptno
3 order by avg(sal);
DEPTNO AVG(SAL)
---------- ----------
30 1566.66667
20 2175
10 2916.66667
在select列表中所有除组函数以外的,所有列都应该包含在group by子句中。(只要写在了select里,就要写在group by里。)
SQL> select job,avg(sal) from emp
2 where job in ('MANAGER','SALESMAN')
3 group by job
4 order by avg(sal);
JOB AVG(SAL)
--------- ----------
SALESMAN 1400
MANAGER 2758.33333
- 多列分组
SQL> select deptno,job,sum(sal) from emp
2 group by deptno,job
3 order by deptno;
DEPTNO JOB SUM(SAL)
---------- --------- ----------
10 CLERK 1300
10 MANAGER 2450
10 PRESIDENT 5000
20 ANALYST 6000
20 CLERK 1900
20 MANAGER 2975
30 CLERK 950
30 MANAGER 2850
30 SALESMAN 5600
9 rows selected.
- 非法使用组函数
select列表中的列或表达式,未包含在组函数中的列,都必须包含于group by子句中。
不能使用where子句过滤组。
可以使用having子句过滤组。
7 HAVING子句
- 过滤分组
- 功能:
1)行已经被分组
2)使用了分组函数
3)满足having子句中条件的分组将被显示
SQL> select avg(sal) m,job from emp
2 group by job
3 having avg(sal) >= 3000
4 order by m;
M JOB
---------- ---------
3000 ANALYST
5000 PRESIDENT
SQL> select deptno ,max(sal) from emp
2 group by deptno
3 having max(sal) >4000;
DEPTNO MAX(SAL)
---------- ----------
10 5000
看表里的部分数据:where
看结果集里的数据:having 一般会跟着group
8 嵌套组函数
- 语法
SELECT column,group_function
FROM table
[WHERE condition]
[GROUP BY group_by_expression]
[HAVING group_condition]
[ORDER BY column];
- 显示平均工资的最大值
SQL> select max(avg(sal)) ma from emp
2 group by deptno;
MA
----------
2916.66667
不能写部门
SQL> select max(avg(sal)) ma,deptno from emp
2 group by deptno;
select max(avg(sal)) ma,deptno from emp
*
ERROR at line 1:
ORA-00937: not a single-group group function