Oracle-分析函数_总结
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Oracle-分析函数_总结相关的知识,希望对你有一定的参考价值。
参考技术A 分析函数是Oracle专门用于解决复杂报表统计需求的功能强大的函数,它可以在数据中进行分组然后基于组计算某种统计值,并且每一组的每一行都可以返回一个统计值。说白了,分析函数就是 over([query_partition_clase] order_by_clause)。比如说,我采用sum求和,rank排序等等,根据什么来呢?over提供一个窗口,使用partition by进行分组,在组内使用order by进行排序。over不能单独使用,要和分析函数:rank(),dense_rank(),row_number()等一起使用
分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是对于每个组返回多行,而聚合函数对于每个组只返回一行。
用于合计的函数:
用于排列的函数:
其他:
而这样使用就是分析函数:
它们得出的结果是相同的,都是:
请注意,这里我们用到了distinct 关键字,如果不用distinct,第2个查询将返回20行数据,即earnings表的每行记录都将返回一行总收入,因为不用distinct的含义是:针对每个打工者计算他/她所在的月份和地区的总收入。
在这个例子中,聚合函数是更好的选择,但在另外一些情形下,我们更应该使用分析函数。下面通过几个实例来介绍排序分析函数的用途。
问题:统计每个月份,不同地区工资最高的前3名。
利用我们传统的聚合函数max可以方便地取出工资最高的一个员工,但是取出多个就无能为力了,同样,如果不分组我们可以通过排序取出工资最高的前3名,但无法实现对多个月份和地区的分组。而采用rank()分析函数,可以方便地实现我们的要求。
完整的语句如下:
结果为:
我们在开窗函数over()中使用earnmonth(月份)和area(地区)作为分组标志,并按照personincome(收入)倒序排列。
注意:RANK()函数有3组,分别是rank(), dense_rank(), row_number(),它们的区别是:
RANK()如果出现两个相同的数据,那么后面的数据就会直接跳过这个排名,比如:当第2名和第3名的利润相同时,rank的结果是1,2,2,4;而dense_rank()则不会跳过这个排名,结果是1,2,2,3;而row_number()哪怕是两个数据完全相同,排名也会不一样,结果是1,2,3,4.
完整的语句如下:
结果为:
完整的语句如下:
结果为:
结果为:
结果为:
在以上例子中,是用rollup()和cube()函数都会对结果集产生null,这时候可用grouping函数来确认该记录是由哪个字段得出来的.
grouping函数用法,带一个参数,参数为字段名,如果当前行是由rollup或者cube汇总得来的,结果就返回1,反之返回0.
完整语句如下:
结果为:
以上语句统计结果和如下语句使用group by的查询结果一样:
说明:Lag和Lead函数可以在一次查询中取出某个字段的前N行和后N行的数据(可以是其他字段的数据,比如根据字段甲查询上一行或下两行的字段乙),原来没有分析函数的时候采用子查询方法,但是比较麻烦:
语法如下:
其中:
统计每个打工者上个月和下个月有没有赚钱(personincome大于0即为赚钱):
结果为:
Oracle SQL常用内置系统函数总结
Oracle数据库 内置系统函数主要分为以下类别:数学函数、字符串函数、日期函数、转换函数、聚合函数、分析聚合函数
一、数学函数 ------------返回数字
abs(n):返回数字n的绝对值
ceil(n):返回>=数字n的最小整数
floor(n):返回<=数字n的最大整数
round(n,[m]):做四舍五入运算,如果m缺省则四舍五入到整数位
m<0,四舍五入到小数点的前m位,m>0四舍五入到小数点的后m位
trunc(n,[m]):截取数字,如果m缺省则将小数位截去
m<0,截取到小数点的前m位,m>0截取到小数点的后m位
1 --Demo:abs()、ceil()、floor()、trunc()
2 SELECT abs(-2.3),
3 ceil(-2.6),ceil(2.6),
4 floor(-2.6),floor(2.6),
5 round(-666.588),round(-666.588,2),round(-666.588,-2),
6 trunc(-666.588),trunc(-666.588,2),trunc(-666.588,-2)
7 FROM dual;
运算结果:
1 ABS(-2.3) CEIL(-2.6) CEIL(2.6) FLOOR(-2.6) FLOOR(2.6) ROUND(-666.588) ROUND(-666.588,2) ROUND(-666.588,-2) TRUNC(-666.588) TRUNC(-666.588,2) TRUNC(-666.588,-2)
2 ---------- ---------- ---------- ----------- ---------- --------------- ----------------- ------------------ --------------- ----------------- ------------------
3 2.3 -2 3 -3 2 -667 -666.59 -700 -666 -666.58 -600
sqrt(x):返回数字x(x必须大于0)的平方根
power(x,y):返回数字x的y次幂,底数x和指数y都可以是任意数字,但是如果底数x为负数则指数y必须为正数
exp(x):返回常量e(2.71828183....)的x次幂
ln(x):返回数字x(x必须大于0)的自然对数
log(x,y):返回以x为底(除0及1的正整数)m的(任何正整数)对数
mod(x,y):返回x除以y的余数,如果数字m=0则返回n
1 --demo:sqrt(),power(),exp(),ln(),log(),mod()
2 SELECT sqrt(4),power(2,3),exp(1),ln(10),log(2,8),mod(5,2)
3 FROM dual
运算结果:
1 SQRT(4) POWER(2,3) EXP(1) LN(10) LOG(2,8) MOD(5,2)
2 ---------- ---------- ---------- ---------- ---------- ----------
3 2 8 2.71828182 2.30258509 3 1
cos(n):返回数字n(弧度单位表示的角度值)的余弦值
cosh(n):返回数字n的双曲余弦值
acos(n):返回数字n的反余弦值,求的结果单位为弧度,n的范围为 -1 < n < 1
sin(n):返回数字n(弧度单位表示的角度值)的正弦值
sinh(n,m):返回数字n的双曲正弦值
asin(n,m):返回数字n的反正弦值,求的结果单位为弧度,n的范围为 -1 < n < 1
tan(n):返回数字n(弧度表示的角度值)的正切值
tanh(n):返回数字n的双曲正切值
atan(n):返回数字n的反正切值,求的结果单位为弧度,n的范围任意数值
atan(n,m):返回数字n/m的反正切值,求的结果单位为弧度,你可以为任意数值,m不可为0
1 --demo:cos(),cosh(),acos(),sin(),sinh(),asin(),tan(),tanh(),atan(),atan()
2 SELECT cos(0.5),cosh(2),acos(1),
3 sin(0.5),sinh(2),asin(0),
4 tan(0.5),tanh(2),atan(8),atan(16/2)
5 FROM dual
运算结果:
1 COS(0.5) COSH(2) ACOS(1) SIN(0.5) SINH(2) ASIN(0) TAN(0.5) TANH(2) ATAN(8) ATAN(16/2)
2 ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
3 0.87758256 3.76219569 0 0.47942553 3.62686040 0 0.54630248 0.96402758 1.44644133 1.44644133
二、字符串函数 ------------返回字符值
ascii(n):返回字符c的ascii值
chr(n):将ascii值转换为对应的字符
initcap(s):将字符串s所有的单词(单词是用.空格或给字母数字字符由空格,控制字符,标点符号进行分隔)的首字母大写,其余小写
lower(s):将字符串s中所有的字符转换为小写
upper(s):将字符串s中所有的字符转换为大写
concat(s1,s2):将字符串s2连接在s1后面,等同于操作符||
length(s):将返回字串s的长度,返回的长度包括其中的所有空格(尾部空格也算);如果s为null,则返回null
1 --ascii(),chr(),concat(),initcap(), lower(),upper(), length(),
2 SELECT ascii(‘A‘),chr(65),concat(‘Hello‘,‘World‘),
3 initcap(‘hello woRld‘),
4 lower(‘HeLLo woRld‘),upper(‘HeLLo woRld‘),
5 length(‘HeLLo woRld‘),length(‘天下英雄出我辈‘)
6 FROM dual
运算结果:
1 ASCII(‘A‘) CHR(65) CONCAT(‘HELLO‘,‘WORLD‘) INITCAP(‘HELLOWORLD‘) LOWER(‘HELLOWORLD‘) UPPER(‘HELLOWORLD‘) LENGTH(‘HELLOWORLD‘)
2 ---------- ------- ----------------------- --------------------- ------------------- ------------------- --------------------
3 65 A HelloWorld Hello World hello world HELLO WORLD 11
lpad(s1,n,s2):在字串s1的左端填充字串s2,直至填充后的s1的总长度为n
如果不指定s2则默认为空格
如果s1的长度>n,则直接返回s1左端的n个字符
rpad(s1,n,s2):在字串s1的右端填充字串s2,直至填充后的s1的总长度为n
如果不指定s2则默认为空格
如果s1的长度>n,则直接返回s1左端的n个字符
1 --demo:lpad、rpad
2 SELECT lpad(‘a‘,10,‘8‘),lpad(‘SnnnnnnnnR‘,6,‘8‘),
3 rpad(‘a‘,10,‘8‘),rpad(‘SnnnnnnnnR‘,6,‘8‘)
4 FROM dual
运算结果:
1 LPAD(‘A‘,10,‘8‘) LPAD(‘SNNNNNNNNR‘,6,‘8‘) RPAD(‘A‘,10,‘8‘) RPAD(‘SNNNNNNNNR‘,6,‘8‘)
2 ---------------- ------------------------ ---------------- ------------------------
3 888888888a Snnnnn a888888888 Snnnnn
instr(s1,s2,n,m):取得子串s2在字串s1中的位置
n表示在s1中开始搜索的位置,m表示字串s2出现的次数
如果n为负数,则表示从尾部开始搜索,n与m默认为1
substr(s1,m,n):取得字串s1从m开始,长度为n的子串,m>0表示从头开始搜索,m<0表示从尾开始
1 -- instr(), substr()
2 SELECT instr(‘888arrayarray‘,‘array‘,1,1) ,instr(‘888arrayarray‘,‘array‘,1,2),
3 instr(‘888arrayarray‘,‘array‘,-1,1),instr(‘888arrayarray‘,‘array‘,-1,2),
4 substr(‘纵横天下‘,1,2),substr(‘array‘,-4,3)
5 FROM dual
运算结果:
INSTR(‘888ARRAYARRAY‘,‘ARRAY‘, INSTR(‘888ARRAYARRAY‘,‘ARRAY‘, INSTR(‘888ARRAYARRAY‘,‘ARRAY‘, INSTR(‘888ARRAYARRAY‘,‘ARRAY‘,
------------------------------ ------------------------------ ------------------------------ ------------------------------
4 9 9 4
ltrim(s1,str):从左端开始逐一取得字串s1左端包含的str中的任何字符
当遇到不是str中的字符是,则结束并返回剩余结果
rtrim(s1,str):从右端开始逐一取得字串s1右端包含的str中的任何字符
当遇到不是str中的字符是,则结束并返回剩余结果
trim(c FROM str):从字串str的头部、尾部、或两端截去字符c(c只能够是一个字符)
当遇到不是str中的字符是,则结束并返回剩余结果
1 SELECT ltrim(‘terry‘,‘t‘),ltrim(‘terry‘,‘ter‘),ltrim(‘terry‘,‘e‘),
2 rtrim(‘terry‘,‘y‘),rtrim(‘terry‘,‘ry‘),rtrim(‘terry‘,‘yre‘),
3 trim(‘e‘ from ‘terry‘),trim(‘t‘ from ‘terry‘),trim(‘y‘ from ‘terryy‘)
4 FROM dual
运行结果:
1 LTRIM(‘TERRY‘,‘T‘) LTRIM(‘TERRY‘,‘TER‘) LTRIM(‘TERRY‘,‘E‘) RTRIM(‘TERRY‘,‘Y‘) RTRIM(‘TERRY‘,‘RY‘) RTRIM(‘TERRY‘,‘YRE‘) TRIM(‘E‘FROM‘TERRY‘) TRIM(‘T‘FROM‘TERRY‘) TRIM(‘Y‘FROM‘TERRYY‘)
2 ------------------ -------------------- ------------------ ------------------ ------------------- -------------------- -------------------- -------------------- ---------------------
3 erry y terry terr te t terry erry terr
replace(s1,s2,s3):将s1字串中的子串s2用s3替代,如果s2为null则返回原来的字串s1
注意:如果s3为null,则会去掉子串s2
translate(s1,froms,tos):将字符串s1按照froms和tos的对应关系进行转换
1 SELECT replace(‘风清扬_array‘,‘风清扬‘,‘令狐冲‘),replace(‘风清扬_array‘,‘风清扬‘),
2 translate(‘aerry‘,‘abcdefgxyz‘,‘888888666‘)
3 FROM dual
4
5 REPLACE(‘风清扬_ARRAY‘,‘风 REPLACE(‘风清扬_ARRAY‘,‘风 TRANSLATE(‘AERRY‘,‘ABCDEFGXYZ‘
6 ------------------------------ ------------------------------ ------------------------------
7 令狐冲_array _array 88rr6
regexp_substr(s1,pattern,position,occurrence,match_parameter):
按照正则表达式pattern从s1字串中的position位置开始
截取第occurrence次出现的匹配pattern的字串,matche_parameter为默认匹配的文本
position,occurrence,matche_parameter 默认为1,1," "
regexp_replace(s1,pattern,position,occurrence,match_parameter):
正则表达式扩展replace的功能,用于按照特定的表达式pattern的规则替换字串串s1
s1指定替换字符串,position指定起始搜索位置
occurrence指定替换出现的第n个字符串
matche_parameter指定默认匹配操作的文本串
regexp_like():用正则表达式扩展后的like
regexp_instr():用正则表达式扩展后的instr
1 SELECT regexp_substr(‘我的箱[email protected]‘,‘[[:lower:]]{1,}[email protected]{1}+[[:alnum:]]{1,}+\.{1}+[[:alpha:]]{1,}‘),
2 regexp_replace(‘这是什么http://www.space.com.tw/product‘,‘http://([[:alnum:]]+\.?){3,4}+[[:print:]]{1,}‘,‘www.terry.com‘)
3 FROM dual
4
5 REGEXP_SUBSTR(‘我的箱HELLOW REGEXP_REPLACE(‘这是什么HT
6 ------------------------------ ------------------------------
7 helloword@126.com 这是什么www.terry.com
三、日期函数
sysdate:返回系统当前日期时间
systimestamp:返回系统当前日期时间和时区
current_date:返回当前回话时区所对应的日期和时间
current_timestamp:返回当前回话时区所对应的日期时间
localtimestamp:返回当前回话时区所对应的日期时间
systimestamp:返回系统当前日期时间和时区
sessiontimezone:返回当前回话所在的时区
dbtimezone:返回资料库所在的时区
1 SELECT sysdate,systimestamp,current_date,current_timestamp,
2 localtimestamp,sessiontimezone,dbtimezone
3 FROM dual
4 YSDATE SYSTIMESTAMP CURRENT_DATE CURRENT_TIMESTAMP LOCALTIMESTAMP SESSIONTIMEZONE DBTIMEZONE
5 ----------- -------------------------------------- ------------ --------------------------------------- ------------------------------ ------------------ ----------
6 2017/10/10 10-OCT-17 10.23.03.532728 AM +08:00 2017/10/10 1 10-OCT-17 10.23.03.532742 AM +08:00 10-OCT-17 10.23.03.532742 AM +08:00 +00:00
add_months(d,n):返回指定日期d之后(或前)的n个月所对应的日期时间;n>0:之后,n<0:之前
extract():用于从特定的日期时间值里取出所需要的特定数据(如日期、月份、日、时间等)
last_day(d):用于返回指定日期所在月份的最后一天
next_day(d,char):返回指定日期后的一个工作日(由char指定)所对应的日前
round(d[,fmt]):返回日期时间的四舍五如结果,如果fmt指定年度則7月1日为分界线
如果fmt指定月則16日为分界线,如果fmt指定天則中午12:00为分界线
trunc(d[,fmt]):用于截断日期时间数据,如果fmt指定年度则结果为本年的1月1日
如果fmt指定月则结果为本月1日,如果fmt空则结果为为截取日期时间数据中的日期
1 SELECT sysdate,add_months(sysdate,4),add_months(sysdate,-4),
2 extract(MONTH from sysdate),last_day(sysdate),next_day(sysdate,‘sunday‘),
3 round(sysdate,‘YEAR‘),round(sysdate,‘MONTH‘),round(sysdate,‘DAY‘),round(sysdate),
4 trunc(sysdate,‘YEAR‘),trunc(sysdate,‘MONTH‘),trunc(sysdate,‘DAY‘),trunc(sysdate)
5 FROM dual
运算结果:
1 SYSDATE ADD_MONTHS(SYSDATE,4) ADD_MONTHS(SYSDATE,-4) EXTRACT(MONTHFROMSYSDATE)
2 ----------- --------------------- ---------------------- -------------------------
3 2017/10/10 2018/2/10 11:29:23 2017/6/10 11:29:23 10
4
5 LAST_DAY(SYSDATE) NEXT_DAY(SYSDATE,‘SUNDAY‘) ROUND(SYSDATE,‘YEAR‘) ROUND(SYSDATE,‘MONTH‘) ROUND(SYSDATE,‘DAY‘)
6 ----------------- -------------------------- --------------------- ---------------------- --------------------
7 2017/10/31 11:29: 2017/10/15 11:29:23 2018/1/1 2017/10/1 2017/10/8
8
9 ROUND(SYSDATE) TRUNC(SYSDATE,‘YEAR‘) TRUNC(SYSDATE,‘MONTH‘) TRUNC(SYSDATE,‘DAY‘) TRUNC(SYSDATE)
10 -------------- --------------------- ---------------------- -------------------- --------------
11 2017/10/10 2017/1/1 2017/10/1 2017/10/8 2017/10/10
to_timestamp(s1,fmt):将符合特定日期和时间按格式的字符串转变为 timestamp 类型
month_between(d1,d2):返回日期d1和d2之间相差的月份数,
如果d1<d2则返回负数,如果d1和d2的天数相同或都是月底则返回整数,否则oracle以每月31天为准来计算结果的小数部份
1 select to_timestamp(‘2015-03-25 11:30:00‘,‘YYYY-MM-DD HH24:MI:SS‘),
2 sysdate,months_between(sysdate,to_date(‘2012/06/30‘,‘YYYY/MM/DD‘))
3 from dual
运算结果:
1 TO_TIMESTAMP(‘2015-03-2511:30:
2 ----------------------------------
3 25-MAR-15 11.30.00.000000000 AM
4
5 SYSDATE MONTHS_BETWEEN(SYSDATE,TO_DATE
6 ----------- ------------------------------
7 2017/10/10 63.3708594683393
四、转换函数
to_date(s1[,fmt[,nlsparams]]):把一个字符串转换为一个DATE类型的变量.
如果指定了fmt,就按fmt格式转换成一个日期类型.
如果没有指定fmt,使用的就是该会话的缺省日期格式.
注:在使用Oracle的to_date函数来做日期转换时,很多Java程序员也许会直接的采用‘yyyy-MM-dd HH:mm:ss‘的格式作为格式进行转换,
但是在Oracle中会引起错误:‘ORA 01810 格式代码出现两次‘,原因是SQL中不区分大小写,MM和mm被认为是相同的格式代码,
所以Oracle的SQL采用了mi代替分钟,即: ‘yyyy-MM-dd HH24:mi:ss‘
1 select to_date(‘2005-01-01 13:14:20‘,‘yyyy-MM-dd HH24:mi:ss‘) from dual;
2 TO_DATE(‘2005-01-0113:14:20‘,‘yyyy-MM-dd HH24:mi:ss‘)
3 ----------------------------------------------------
4 2005/1/1 13:14:20
to_char(num[,fmt]):把日期或数字转换字符串。
如果指定了格式字符串fmt,则按指定格式转换。
--日期转换字符串--
select to_char(sysdate, ‘yyyy-mm-dd hh24:mi:ss‘),
to_char(sysdate, ‘yyyymmddhh24miss‘),
to_char(258.45)
from dual;
运行结果:
1 TO_CHAR(SYSDATE,‘yyyy-mm-dd hh24:mi:ss‘)
2 ------------------------------
3 2017-10-10 15:53:31
4
5 TO_CHAR(SYSDATE,‘yyyymmddhh24miss‘),
6 ------------------------------
7 20171010155331
8
9 TO_CHAR(258.45)
10 ---------------
11 258.45
cast(expr AS type_name): 用于将某种数据类型的数据显式转换为另一种数据类型的数据。
函数的参数有两部分,源值expr和目标数据类型type_name,中间用AS关键字分隔。
1 select cast(‘123.4567‘ AS NUMBER(10,2)),
2 cast(‘2323‘ as char(6)),
3 cast(to_date(‘20110419010101‘,‘yyyy-mm-dd hh24:mi:ss‘) as date)
4 from dual;
运行结果:
1 CAST(‘123.4567‘ASNUMBER(10,2))
2 ------------------------------
3 123.46
4
5 CAST(‘2323‘ASCHAR(6))
6 ---------------------
7 2323
8
9 CAST(TO_DATE(‘20110419010101‘,‘YYYY-MM-DD HH24:MI:SS‘) AS DATE)
10 ---------------------------------------------------------------
11 2011/4/19 1:01:01
numtodsinterval(num,expr): 将数字按转换单位转换成相应 interval day to second 时间段类型,
转换单位expr必须是以下值之一:day,hour,minute 或 second。
numtoyminterval(num,expr): 将数字按转换单位转换成相应 interval year to month 时间段类型,
转换单位expr必须是以下值之一:day,hour,year 或 month。
1 select NUMTOYMINTERVAL(100000000, ‘MONTH‘),
2 NUMTOYMINTERVAL(100000, ‘YEAR‘),
3 NUMTODSINTERVAL(150, ‘DAY‘),
4 NUMTODSINTERVAL(1500, ‘HOUR‘),
5 NUMTODSINTERVAL(15000, ‘MINUTE‘),
6 NUMTODSINTERVAL(150000, ‘SECOND‘)
7 from dual;
运行结果:
1 NUMTOYMINTERVAL(100000000,‘MONTH‘)
2 --------------------------------------------------------------------------------
3 +008333333-04
4
5 NUMTOYMINTERVAL(100000,‘YEAR‘)
6 --------------------------------------------------------------------------------
7 +000100000-00
8
9 NUMTODSINTERVAL(150,‘DAY‘)
10 --------------------------------------------------------------------------------
11 +000000150 00:00:00.000000000
12
13 NUMTODSINTERVAL(1500,‘HOUR‘)
14 --------------------------------------------------------------------------------
15 +000000062 12:00:00.000000000
16
17 NUMTODSINTERVAL(15000,‘MINUTE‘)
18 --------------------------------------------------------------------------------
19 +000000010 10:00:00.000000000
20
21 NUMTODSINTERVAL(150000,‘SECOND‘)
22 --------------------------------------------------------------------------------
23 +000000001 17:40:00.000000000
24
to_dsinterval(s1): 将字符串s1转换为interval day TO second类型的数据
to_yminterval(s1): 将字符串s1转换为interval year to month类型的数据。
1 select to_dsinterval(‘150 08:30:00‘),
2 to_dsinterval(‘80 12:30:00‘),
3 to_yminterval(‘03-11‘),
4 to_yminterval(‘01-05‘)
5 from dual;
运行结果:
1 TO_DSINTERVAL(‘15008:30:00‘)
2 ---------------------------------------------------------------------
3 +000000150 08:30:00.000000000
4
5 TO_DSINTERVAL(‘8012:30:00‘)
6 ---------------------------------------------------------------------
7 +000000080 12:30:00.000000000
8
9 TO_YMINTERVAL(‘03-11‘)
10 ---------------------------------------------------------------------
11 +000000003-11
12
13 TO_YMINTERVAL(‘01-05‘)
14 ---------------------------------------------------------------------
15 +000000001-05
五、SQL聚合函数(分组函数)
min( [distinct|all] <列名> | * ): 求一列值中的最小值
max( [distinct|all] <列名> ): 求一列值中的最大值
sum( [distinct|all] <列名> ): 计算一列值的总和
count( [distinct|all] <列名> | * ): 统计一列值的中的个数 ,为*时统计记录的条数
avg( [distinct|all]< 列名> ): 计算一列值的平均值
1 select count(distinct ename),count(*),
2 min(sal),
3 max(sal),
4 sum(sal),
5 avg(sal)
6 from emp;
运行结果:
1 COUNT(DISTINCTENAME) COUNT(*) MIN(SAL) MAX(SAL) SUM(SAL) AVG(SAL)
2 -------------------- ---------- ---------- ---------- ---------- ----------
3 14 14 800 5000.25 29226.58 2087.61285
六、分析聚合函数
rank(expr1,expr2,...) within group(order by col1,col2,...):返回特定数值在统计数值中的排序值,expr1,expr2,...必须为常数
rank() over( [query_partition_clause] order_by_clause ) :从一个查询结果中计算每一行的排序值,排序基于order_by_clause子句中的value_exprs指定的字段
1 -- demo:返回1530在所有工资中所占的等级
2 select rank(1530) within group(order by sal asc) rank_level
3 from emp;
4 RANK_LEVEL
5 ----------
6 8
1 --demo:返回所有部门的每个员工的工资等级
2 select rank() over(order by sal asc) as rank_level,ename
3 from emp where deptno = 30;
4
5 RANK_LEVEL ENAME
6 ---------- ----------
7 1 JAMES
8 2 WARD
9 3 MARTIN
10 4 TURNER
11 5 ALLEN
12 6 BLAKE
dense_rank(expr1,expr2,...) within group(order by expr1,expr2,...):返回特定数值在一组行数据中的等级
dense_rank() over( [query_partition_clause] order_by_clause ):从一个查询结果中计算每一行的排序值,排序基于order_by_clause子句中的value_exprs指定的字段
注:dense_rank与rank()的区别:
聚合函数RANK 和 dense_rank 主要的功能是计算一组数值中的排序值。
dense_rank与rank()用法相当,dence_rank在并列关系中相关等级不会跳过,rank则会跳过.rank()是跳跃排序,
有两个第二名时接下来就是第四名(同样是在各个分组内) dense_rank()是连续排序,有两个第二名时仍然跟着第三名。
1 -- demo:返回1530在所有工资中所占的等级
2 SQL> select dense_rank(1530) within group(order by sal asc) dense_rank_level
3 from emp;
4 DENSE_RANK_LEVEL
5 ----------------
6 8
1 --demo:返回所有部门的每个员工的工资等级
2 SQL> select dense_rank() over(order by sal asc) as rank_level,ename
3 from emp where deptno = 20;
4 RANK_LEVEL ENAME
5 ---------- ----------
6 1 SMITH
7 2 ADAMS
8 3 JONES
9 4 FORD
10 4 SCOTT
row_number() over (partition by col1 order by col2) : 表示根据col1分区,在分组内部根据 col2排序,而这个值就表示每组内部排序后的
顺序编号(组内连续的唯一的) row_number() 返回的主要是“行”的信息,并没有排名.
1 --demo:根据deptno分组,在分组内部根据 sal排序
2 SQL> select row_number() over(partition by deptno order by sal) from emp where deptno < 30;
3 ROW_NUMBER()OVER(PARTITIONBYDE
4 ------------------------------
5 1
6 2
7 3
8 1
9 2
10 3
11 4
12 5
percent_rank(expr1,expr2,...) within group(order by expr1,expr2,...):返回特定数值的统计数值在统计级别中所占的比例
1 SQL> select ename,percent_rank() over(order by sal) percent,rank() over(order by sal) ,sal from emp;
2 ENAME PERCENT RANK()OVER(ORDERBYSAL) SAL
3 ---------- ---------- ---------------------- ---------
4 SMITH 0 1 800.00
5 JAMES 0.07692307 2 950.00
6 ADAMS 0.15384615 3 1100.00
7 WARD 0.23076923 4 1250.00
8 MARTIN 0.30769230 5 1250.25
9 TURNER 0.38461538 6 1500.00
10 MILLER 0.46153846 7 1500.25
11 ALLEN 0.53846153 8 1600.00
12 CLARK 0.61538461 9 2450.83
13 BLAKE 0.69230769 10 2850.00
14 JONES 0.76923076 11 2975.00
15 SCOTT 0.84615384 12 3000.00
16 FORD 0.84615384 12 3000.00
17 KING 1 14 5000.25
percentile_cont(percent_expr)within group(order by expr):返回在统计级别中处于某个百分点的特定数值(按照连续分布模型确定)
percentile_disc(percent_expr)within group(order by expr): 返回在统计级别中处于某个百分点的特定数值(按照离散分布模型确定)
1 SQL> select percentile_cont(0.25)within group(order by sal) from emp;
2 PERCENTILE_CONT(0.25)WITHINGRO
3 ------------------------------
4 1250.0625
1 SQL> select percentile_disc(0.25)within group(order by sal) from emp;
2 PERCENTILE_DISC(0.25)WITHINGRO
3 ------------------------------
4 1250
first:取得排序等级的第一级,然后使用分组函数汇总该等级的数据,该函数不能够单独使用,必须与其它分组函数结合使用。
last:取得排序等级的最后一级,然后使用分组函数汇总该等级的数据,该函数不能够单独使用,必须与其它分组函数结合使用。
1 SQL> SELECT max(sal)keep(dense_rank first order by sal),deptno from emp group by deptno;
2 MAX(SAL)KEEP(DENSE_RANKFIRSTOR DEPTNO
3 ------------------------------ ------
4 1500.25 10
5 800 20
6 950 30
1 SQL> SELECT max(sal)keep(dense_rank last order by sal),deptno from emp group by deptno;
2 MAX(SAL)KEEP(DENSE_RANKLASTORD DEPTNO
3 ------------------------------ ------
4 5000.25 10
5 3000 20
6 2850 30
over ([partition by col1] order by col2) ) :开窗函数,表示依col1分区,依col2在分组类排序,
over函数不能够单独使用,必须和其它的分组/分析函数配合使用,over函数不可用在where子句中。
1 SQL> select ename 姓名,deptno 部门,sal 薪水,
2 2 sum(sal) over(partition by deptno order by sal),
3 3 sum(sal) over(partition by deptno),
4 4 sum(sal) over(order by sal),
5 5 sum(sal) over()
6 6 from emp;
7 姓名 部门 薪水 SUM(SAL)OVER(PARTITIONBYDEPTNO SUM(SAL)OVER(PARTITIONBYDEPTNO SUM(SAL)OVER(ORDERBYSAL) SUM(SAL)OVER()
8 ---------- ------ --------- ------------------------------ ------------------------------ ------------------------ --------------
9 SMITH 20 800.00 800 10875 800 29226.58
10 JAMES 30 950.00 950 9400.25 1750 29226.58
11 ADAMS 20 1100.00 1900 10875 2850 29226.58
12 WARD 30 1250.00 2200 9400.25 4100 29226.58
13 MARTIN 30 1250.25 3450.25 9400.25 5350.25 29226.58
14 TURNER 30 1500.00 4950.25 9400.25 6850.25 29226.58
15 MILLER 10 1500.25 1500.25 8951.33 8350.5 29226.58
16 ALLEN 30 1600.00 6550.25 9400.25 9950.5 29226.58
17 CLARK 10 2450.83 3951.08 8951.33 12401.33 29226.58
18 BLAKE 30 2850.00 9400.25 9400.25 15251.33 29226.58
19 JONES 20 2975.00 4875 10875 18226.33 29226.58
20 FORD 20 3000.00 10875 10875 24226.33 29226.58
21 SCOTT 20 3000.00 10875 10875 24226.33 29226.58
22 KING 10 5000.25 8951.33 8951.33 29226.58 29226.58
23 14 rows selected
1 SQL> select ename 姓名,deptno 部门,sal 薪水,salary_order 排序 from (
2 2 select ename,deptno,sal,row_number() over(partition by deptno order by sal desc) salary_order
3 3 from emp)emp_temp;
4 姓名 部门 薪水 排序
5 ---------- ------ --------- ----------
6 KING 10 5000.25 1
7 CLARK 10 2450.83 2
8 MILLER 10 1500.25 3
9 SCOTT 20 3000.00 1
10 FORD 20 3000.00 2
11 JONES 20 2975.00 3
12 ADAMS 20 1100.00 4
13 SMITH 20 800.00 5
14 BLAKE 30 2850.00 1
15 ALLEN 30 1600.00 2
16 TURNER 30 1500.00 3
17 MARTIN 30 1250.25 4
18 WARD 30 1250.00 5
19 JAMES 30 950.00 6
20 14 rows selected
group_id():区分分组结果中的重复行
grouping(expr):用于确定分组结果是否用到了特定的运算式
返回值0表示用到了该运算式,返回值1表死未用到该运算式
grouping_id(expr1[,expr2],,,):用于返回对应于特定行的分组位向量的值
未完待续
以上是关于Oracle-分析函数_总结的主要内容,如果未能解决你的问题,请参考以下文章