Oracle单组函数、分组函数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sl1992/article/details/84350873


Oracle函数、Oracle单组函数、Oracle多行函数

1.函数基础

1.1SQL函数

函数概念
注意:函数可以没有参数,但必须要有返回值。

1.2两种SQL函数

两种SQL函数

2.单行函数

2.1说明

单行函数:

  • 操作数据对象
  • 接收参数返回一个结果
  • 只对一行进行变换
  • 每行返回一个结果
  • 可以转换数据类型
  • 可以嵌套
  • 参数可以是一列或一个值

语法:

function_name [(arg1, arg2,...)]

单行函数

2.2字符函数

字符函数

函数 描述 示例 结果
lower 全部转为小写 lower(‘Hello World’) hello world
upper 全部转为大写 upper(‘Hello World’) HELLO WORLD
initcap 首字母转为大写 initcap(‘hello world’) Hello World
concat 连接两个字符串 concat(‘Hello’,‘World’) HelloWorld
substr 在字符串str中从第m个位置开始取n个字符(位置从1开始) substr(‘Hello World’,2,4) ello
length 求长度 length(‘Hello World’) 11
instr 从字符串strA中找出str所在的位置(返回第1个找到的,位置从1开始) instr(‘Hello World!Hello’, ‘llo’) 3
lpad 把字符串str补齐到n个长度,不足就在左边加指定字符c;
如果str.length>n就取str的前n个字符
lpad(‘ith’, 5, ‘qq’) qqith
rpad 把字符串str补齐到n个长度,不足就在右边加指定字符c;
如果str.length>n就取str的前n个字符(也是从前面取)
rpad(‘ith’, 5, ‘qq’) ithqq
trim 从字符串str的两端去掉字符(默认去掉空格) trim(’ solang ') solang
replace 将strA中的字符串strB替换为str replace(‘asolaanga’, ‘a’, ‘’) solng

substr(str, startPosition, count)如果第3个参数不指定(即不指定截取几个字符),就表示到最后。

lpadrpad

SQL> select lpad('smith', 3, '*') from dual;

LPA
---
smi

SQL> select rpad('smith', 3, '*') from dual;

RPA
---
smi

trim将两端指定的字符去掉,使用方式特殊,注意:指定的字符只能指定一个

SQL> select trim('a' from 'aabaslaabaa') from dual;

TRIM('A
-------
baslaab

2.2.1大小写控制函数

这类函数用于改变字符的大小写。
大小写控制函数

SQL> select * from emp where lower(ename) = 'smith';

2.2.2字符控制函数

字符控制函数

2.3数字函数

函数 描述 示例 结果
round 四舍五入 round(45.992, 2) 45.99
trunc 截断 trunc(45.992, 1) 45.9
mod 求余 mod(1600, 300) 100

round保留的位数可以指定正、零、负数。

SQL> select round(45.992, 2) from dual;

ROUND(45.992,2)
---------------
	  45.99

SQL> select round(45.992, 0) from dual;	 

ROUND(45.992,0)
---------------
	     46

SQL> select round(45.992, -1) from dual;	 

ROUND(45.992,-1)
----------------
	      50

SQL> select round(45.992, -2) from dual;	 

ROUND(45.992,-2)
----------------
	       0	  

trunc舍掉后面的数,保留的位数可以指定正、零、负数。

SQL> select trunc(45.992, 1) from dual;

TRUNC(45.992,1)
---------------
	   45.9

SQL> select trunc(45.992, 0) from dual;

TRUNC(45.992,0)
---------------
	     45

SQL> select trunc(45.992, -1) from dual;

TRUNC(45.992,-1)
----------------
	      40

SQL> select trunc(45.992, -2) from dual;

TRUNC(45.992,-2)
----------------
	       0

mod取余数

SQL> select mod(1600, 300) from dual;

MOD(1600,300)
-------------
	  100

SQL> select mod(16, 5) from dual;    

 MOD(16,5)
----------
	 1

SQL> select mod(15, 5) from dual;

 MOD(15,5)
----------
	 0	  

2.4日期

MySQL中日期类型:date, time, datetime;Oracle中只有date。

Oracle中的日期型数据实际含有两个值: 日期和时间。函数SYSDATE返回:日期和时间

默认的日期格式是DD-MON-RR

SQL> select sysdate-1 yesterday, sysdate today, sysdate+1 tomorrow from dual;

YESTERDAY TODAY     TOMORROW
--------- --------- ---------
19-NOV-18 20-NOV-18 21-NOV-18

2.4.1日期的数学运算

在日期上加上或减去一个数字结果仍为日期。

两个日期相减返回日期之间相差的天数

可以用数字除24来向日期中加上或减去小时。

SQL> select ename,(sysdate-hiredate) "day",(sysdate-hiredate)/7 "week", (sysdate-hiredate)/30 "month",(sysdate-hiredate)/365 "year" from emp;

当前时间,当前时间前一小时,当前时间前一分钟。

SQL> select sysdate,sysdate - 1/24,sysdate - 1/24/60 from dual;

日期小时

2.4.2日期函数

日期函数

默认的日期格式是DD-MON-RR

SQL> select sysdate from dual;

SYSDATE
---------
21-NOV-18
函数 描述 示例 结果
months_between 两个日期相差的月数 months_between(sysdate, ‘21-SEP-2018’) 2
add_months 向指定日期中加上若干月数 add_months(sysdate, -1) 21-OCT-18
next_day 指定日期的下一个日期 next_day(sysdate, ‘THUR’) 22-NOV-18
last_day 本月的最后一天 last_day(sysdate) 30-NOV-18
round 日期四舍五入 round(sysdate, ‘month’) 01-DEC-18
trunc 日期截断 trunc(sysdate, ‘month’) 01-NOV-18

months_between两个日期相差的月数

SQL> select months_between(sysdate, '21-SEP-2018') from dual;

MONTHS_BETWEEN(SYSDATE,'21-SEP-2018')
-------------------------------------
				    2

SQL> select months_between(sysdate, '21-DEC-2018') from dual;

MONTHS_BETWEEN(SYSDATE,'21-DEC-2018')
-------------------------------------
				   -1

SQL> select months_between(sysdate, '02-NOV-2018') from dual;

MONTHS_BETWEEN(SYSDATE,'02-NOV-2018')
-------------------------------------
			   .642333483		   

add_months向指定日期中加上若干月数

SQL> select add_months(sysdate, 1) from dual;

ADD_MONTH
---------
21-DEC-18

SQL> select add_months(sysdate, -1) from dual;

ADD_MONTH
---------
21-OCT-18	

next_day从某个日期算起,下一个出现该星期几的日期

## 今天21号周三,下一个周四是明天
SQL> select next_day(sysdate, 'THUR') from dual;

NEXT_DAY(
---------
22-NOV-18

## 今天21号周三,下一个周三是28号
SQL> select next_day(sysdate, 'WED') from dual; 

NEXT_DAY(
---------
28-NOV-18

last_day本月的最后一天

SQL> select last_day(sysdate) from dual;

LAST_DAY(
---------
30-NOV-18

SQL> select last_day(sysdate-22) from dual;

LAST_DAY(
---------
31-OCT-18

round日期四舍五入,四舍五入年表示月份在7月-12月的,会进位到年份的下一年1月1日,月份在1月-6月的表示当年1月1日;四舍五入月表示天份在16号及以后的天数,会进位到下一月1日,天份在1-15号表示当月1日;四舍五入日表示返回未来日期离给定日期最近的星期日,如果给定日期是星期日,那么四舍五入日返回给定日期。

SQL> select round(sysdate, 'year') from dual;

ROUND(SYS
---------
01-JAN-19

SQL> select round(sysdate, 'month') from dual;

ROUND(SYS
---------
01-DEC-18

SQL> select round(sysdate, 'day') from dual;

ROUND(SYS
---------
25-NOV-18

## 11月30号周五,未来最近的周日是12月2号      
SQL> select round(sysdate + 9, 'day') from dual;

ROUND(SYS
---------
02-DEC-18      

trunc日期截断,截断年表示日期当年1月1日,截断月表示日期当月1号,截断日表示返回过去日期离给定日期最近的星期日,如果给定日期是星期日,那么截断日返回给定日期。

SQL> select trunc(sysdate, 'year') from dual;

TRUNC(SYS
---------
01-JAN-18

SQL> select trunc(sysdate, 'month') from dual;

TRUNC(SYS
---------
01-NOV-18

SQL> select trunc(sysdate, 'day') from dual;

TRUNC(SYS
---------
18-NOV-18  

## 11月3号周六,过去最近的周日是10月28号
SQL> select trunc(sysdate - 18 , 'day') from dual;

TRUNC(SYS
---------
28-OCT-18

查找给定日期的第一天(就是几月1日)。

SQL> select last_day(add_months(sysdate, -1)) + 1 from dual;

LAST_DAY(
---------
01-NOV-18

SQL> select trunc(sysdate, 'month') from dual;

TRUNC(SYS
---------
01-NOV-18

2.5转换函数

转换函数

隐式数据类型转换

Oracle自动完成下列转换:
隐形转换函数

显式数据类型转换
显性转换函数

2.5.1TO_CHAR函数对日期的转换

语法:TO_CHAR(date, ‘format_model’)

格式:

必须包含在单引号中而且大小写敏感。此处大小写敏感不针对YYYY MM DD等这种数字格式。

可以包含任意的有效的日期时间格式

2.5.1.1日期格式的元素

格式 说明 举例
YYYY Full year in numbers(数字全年) 2018
YEAR Year spelled out(年的英文全称) TWENTY EIGHTEEN
MM Two-digit value of month(两位数月份) 11
MONTH Full name of the month(月的全称) NOVEMBER
DY Three-letter abbreviation of the day of the week(三字母缩写的星期几) THU
DAY Full name of the day of the week(星期几全称) THURSDAY
DD Numeric day of the month(数字天数) 22

格式中首字母大写并且和首字母没有组成连续2个及以上大写字母,则显示结果中只有首字母大写;首字母大写并且和首字母组成连续两个大写字母,则全部显示大写。除格式全大写结果显示全部为大写,其它情况都是小写结果。

SQL> select to_char(sysdate, 'YYYY,yyyy,YYyy') from dual;

TO_CHAR(SYSDAT
--------------
2018,2018,2018
       
SQL> select to_char(sysdate, 'YEAR-year-Year-YEar-yeAR') from dual;

TO_CHAR(SYSDATE,'YEAR-YEAR-YEAR-YEAR-YEAR')
--------------------------------------------------------------------------------
TWENTY EIGHTEEN-twenty eighteen-Twenty Eighteen-TWENTY EIGHTEEN-twenty eighteen  

SQL> select to_char(sysdate,'MONTH,month,Month,MOnth,MonTh') from dual;

TO_CHAR(SYSDATE,'MONTH,MONTH,MONTH,MONTH,MONTH')
--------------------------------------------------------------------------------
NOVEMBER ,november ,November ,NOVEMBER ,November
        
SQL> select to_char(sysdate,'DY,dy,Dy,dY') from dual;
        
TO_CHAR(SYSDATE,'DY,DY,DY,DY')
---------------------------------------------------
THU,thu,Thu,thu    
        
SQL> select to_char(sysdate,'DAY,day,Day,DAy') from dual;

TO_CHAR(SYSDATE,'DAY,DAY,DAY,DAY')
--------------------------------------------------------------------------------
THURSDAY ,thursday ,Thursday ,THURSDAY        

2.5.1.2时间格式的元素

AMPM大小写敏感外,其它数字格式对大小写不敏感。

格式 说明 举例
HH 12时制小时数 09
HH24 24时制小时数 21
MI 分钟数 58
SS 秒数 22
AM 上午 PM
PM 下午 PM
SQL> select to_char(sysdate,'HH24:MI:SS AM HH Pm') from dual; 

TO_CHAR(SYSDATE,'
-----------------
21:58:22 PM 09 Pm

日期格式和时间格式可以任意组成有效的日期时间格式。

SQL> select to_char(sysdate,'yyyy-mm-dd hh:mi:ss') from dual;

TO_CHAR(SYSDATE,'YY
-------------------
2018-11-22 10:04:02

SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;

TO_CHAR(SYSDATE,'YY
-------------------
2018-11-22 22:04:22

如果格式中有其它字符,需要使用双引号引起来。

SQL> select to_char(sysdate, 'yyyy"年"mm"月"dd"日" hh24"时"mi"分"ss"秒"') from dual;

TO_CHAR(SYSDATE,'YYYY"年"MM"月"DD
---------------------------------
20181122221433

2.5.2TO_CHAR函数对数字的转换

语法:TO_CHAR(number, ‘format_model’)

下面是在TO_CHAR函数中经常使用的几种格式:
TOCHAR对数字的转换

本地货币符号不区分大小写,小写的l也可以,不过尽量用大写,方便区分。
由于数据库编码使用AMERICAN_AMERICA.AL32UTF8,所有本地货币符号为$

格式化位数不够时,返回格式化位数+1长度的#。
0补齐指定位数,.小数点表示格式化小数点后的位数,,千位符表示展示数字的格式。

货币符号

SQL> select lower(ename), to_char(sal, 'L999999') from emp where sal < 1250;

LOWER(ENAM TO_CHAR(SAL,'L999
---------- -----------------
smith			$800
adams		       $1100
james			$950

SQL> select lower(ename), to_char(sal, '$999999') from emp where sal < 1250;

LOWER(ENAM TO_CHAR(
---------- --------
smith	       $800
adams	      $1100
james	       $950

0补齐指定位数

SQL> select lower(ename), to_char(sal, '$00000') from emp where sal < 1250;

LOWER(ENAM TO_CHAR
---------- -------
smith       $00800
adams       $01100
james       $00950

## 格式化位数不够,返回格式化位数+1长度的#
SQL> select lower(ename), to_char(sal, '00') from emp where sal < 1250;

LOWER(ENAM TO_
---------- ---
smith	   ###
adams	   ###
james	   ###   
      
SQL> select lower(ename), to_char(sal, '000') from emp where sal < 1250;

LOWER(ENAM TO_C
---------- ----
smith	    800
adams	   ####
james	    950      

.格式化小数点后的位数

SQL> select lower(ename), to_char(sal, '000.') from emp where sal < 1250;

LOWER(ENAM TO_CH
---------- -----
smith	    800.
adams	   #####
james	    950.
      
SQL> select lower(ename), to_char(sal, '0000.000') from emp where sal < 1250;

LOWER(ENAM TO_CHAR(S
---------- ---------
smith	    0800.000
adams	    1100.000
james	    0950.000      

,千位符展示数字的格式

SQL> select lower(ename), to_char(sal, '999999') from emp where sal < 1250;

LOWER(ENAM TO_CHAR
---------- -------
smith	       800
adams	      1100
james	       950

SQL> select lower(ename), to_char(sal, '$999,999.99') from emp where sal < 1250;

LOWER(ENAM TO_CHAR(SAL,
---------- ------------
smith	   $800.00
adams	 $1,100.00
james	   $950.00
                   
SQL> select lower(ename), to_char(sal, '$999,99.0') from emp where sal < 1250;

LOWER(ENAM TO_CHAR(SA
---------- ----------
smith	      $8,00.0
adams	     $11,00.0
james	      $9,50.0                   

2.5.3TO_NUMBER和TO_DATE函数

TONUMBER和TODATE

2.5.3.1TO_NUMBER

语法:TO_NUMBER(str[, ‘format_model’])
将字符转换成数字。

'3'已隐式转换为Number类型,再减去2。

SQL> select '3' - 2 from dual;

     '3'-2
----------
	 1
		       
SQL> select to_number('3','999') - 2 from dual;

TO_NUMBER('3','999')-2
----------------------
		     1		
             
SQL> select to_number('$3','$999') - 2 from dual;

TO_NUMBER('$3','$999')-2
------------------------
		       1             

带有货币符号的数字字符串显式转换为数字类型,再减去2。

2.5.3.2TO_DATE

语法:TO_DATE(str[, ‘format_model’])
将字符转换成日期。

SQL> select to_date('20181122', 'yyyymmdd') from dual;

TO_DATE('20181122'
------------------
22-NOV-18

2.6通用函数

这些函数适用于任何数据类型,同时也适用于空值

函数 描述
NVL(expr1, expr2) expr1为NULL,返回expr2;不为NULL,返回expr1
NVL2(expr1, expr2, expr3) expr1不为NULL,返回expr2;为NULL,就返回expr3
(expr1 != null ? expr2 : expr3)
NULLIF(expr1, expr2) expr1和expr2相等返回NULL,不相等返回expr1
COALESCE(expr1, expr2, …,exprn) COALESCE与NVL相比的优点在于COALESCE可以同时处理交替的多个值。
如果第一个表达式为空,则返回下一个表达式,对其他的参数进行COALESCE。
即:找第一个不为空的值。
SQL> select empno,ename,nvl(comm,0) from emp;
SQL> select empno,ename,nvl2(comm,sal+comm,sal) from emp;
SQL> select nullif('12','13'),nullif('12','12') from dual;                                

NU N
-- -
12

SQL> select empno,ename,coalesce(comm,null,90) from emp;

2.7条件表达式

在SQL语句中用于实现IF-THEN-ELSE逻辑。

使用两种方法:
CASE表达式:SQL99的语法,比较繁琐
DECODE函数:Oracle自己的语法,类似Java,比较简洁

2.7.1CASE表达式

CASE表达式
根据员工的职位涨工资:总裁(PRESIDENT)1000、经理(MANAGER)800、其他400。

CASE用法一:

select 
    empno, 
    lower(ename), 
    job, 
    sal 原来的工资, 
    (CASE job WHEN 'PRESIDENT' THEN sal+1000 WHEN 'MANAGER' THEN sal+800 ELSE sal+400 END) 涨后的工资 
from 
	emp;

CASE用法二:

select 
	empno, 
	lower(ename), 
	job, 
	sal 原来的工资, 
	(CASE WHEN job='PRESIDENT' THEN sal+1000 WHEN job='MANAGER' THEN sal+800 ELSE sal+400 END) 涨后的工资 
from 
	emp;		

2.7.2DECODE函数

DECODE函数
decode(变量, 值1, 则a, 值2, 则b, … default)

select 
    empno, 
    lower(ename), 
    job, 
    sal 原来的工资, 
    (DECODE(job, 'PRESIDENT', sal + 1000,
            'MANAGER', sal+800,
            sal +400)
    ) 涨后的工资 
from 
	emp;

default可以不写

select 
    empno, 
    lower(ename), 
    job, 
    sal 原来的工资, 
    (DECODE(job, 'PRESIDENT', sal + 1000,
            'MANAGER', sal+800)
    ) 涨后的工资 
from 
	emp;

DECODE函数不写默认值

2.8函数嵌套

单行函数可以嵌套。
嵌套函数的执行顺序是由内到外。
函数嵌套

3.分组函数

3.1概念

分组函数作用于一组数据,并对一组数据返回一个值。

3.2语法

SELECT [column,] group function(column), ...
FROM table
[WHERE condition]
[GROUP BY group_by_expression] 
[HAVING group_condition]
[ORDER BY column];

3.3类型

函数 描述
COUNT 数量
SUM 总和
MAX 最大值
MIN 最小值
AVG 平均值

对数值型数据使用AVGSUM函数,可以对任意数据类型的数据使用MINMAX函数。

select 
    max(sal) 最高工资, 
    min(sal) 最低工资, 
    avg(sal) 平均工资, 
    sum(sal) 所有员工的工资和, 
    count(sal) 领工资的员工数量
from emp;

组函数

3.4COUNT函数

  • COUNT(*) 返回表中记录总数
  • COUNT(expr) 返回expr不为空的记录总数
  • COUNT(DISTINCT expr) 返回expr非空且不重复的记录总数
select count(*),count(comm),count(distinct sal) from emp;

COUNT函数

3.5组函数忽略空值

注意: 组函数会自动过滤null值。

例,查询所有员工的平均奖金(有人的奖金为null)

SQL> select sum(comm)/count(*) 平均奖金 from emp; 

  平均奖金
----------
146.666667

SQL> select avg(comm) from emp;

 AVG(COMM)
----------
       550

在组函数中使用NVL函数,NVL函数使分组函数无法忽略空值。

SQL> select avg(nvl(comm, 0)) from emp;

AVG(NVL(COMM,0))
----------------
      146.666667

3.6分组数据

可以使用GROUP BY子句将表中的数据分成若干组。

GROUP BY,写在FROM后,如果有WHERE,就在WHERE后面。

①在SELECT列表中所有未包含在组函数中的列都应该包含在GROUP BY子句中。

select deptno,avg(sal) from emp group by deptno;

分组数据1

②包含在GROUP BY子句中的列不必包含在SELECT列表中。

select avg(sal) from emp group by deptno;

分组数据2

③按一个列分组

④按多个列分组,注意:GROUP BY子句中不能使用列别名

select deptno deptid,job,sum(sal) from emp group by deptno,job;

分组函数多个列分组
参与分组的多个列有一个不相同就是不同的组。

⑤不能在WHERE子句中使用组函数,可以在HAVING子句中使用组函数。

3.7过滤分组

使用HAVING子句过滤分组:

行已经被分组,分完组后再进行过滤,只显示满足HAVING子句中条件的结果。HAVING子句中使用了组函数。

GROUP BYHAVING中都不可以使用别名

WHERE的区别:
HAVING是分完组后再进行过滤。
WHERE是先过滤,再进行分组操作。
如果可以,尽量写WHERE条件,不写HAVING

select 
	deptno deptid,job,sum(sal) 
from emp 
group by deptno,job 
having sum(sal) > 4000
order by deptid;

过滤分组

3.8组函数嵌套

显示平均工资的最大值:

select max(avg(sal)) from emp group by deptno;

组函数嵌套

猜你喜欢

转载自blog.csdn.net/sl1992/article/details/84350873