Oracle工作中常用函数的总结

一、常用函数详解

【a】nvl(a,b)函数: 如果a的值为空,那么取b的值

with temp1 as
 (select '张三' as name, '10' as text from dual),
temp2 as
 (select '' as name, '20' as text from dual),
temp3 as
 (select '李四' as name, '' as text from dual)

--nvl(a,b)函数: 如果a的值为空,那么取b的值
select nvl(name, '无名氏') as name, nvl(text, '未知') as text
  from temp1
union all
select nvl(name, '无名氏') as name, nvl(text, '未知') as text
  from temp2
union all
select nvl(name, '无名氏') as name, nvl(text, '未知') as text from temp3

Oracle工作中常用函数的总结_第1张图片

【b】nvl2(a,b,c)函数: 如果a的值不为空,那么取b的值,如果a的值为空,那么取c的值(类似三目运算符)

with temp1 as
 (select '张三' as name, '10' as text from dual),
temp2 as
 (select '' as name, '20' as text from dual),
temp3 as
 (select '李四' as name, '' as text from dual)

--nvl2(a,b,c)函数: 如果a的值不为空,那么取b的值,如果a的值为空,那么取c的值(类似三目运算符)
select nvl2(name, name, '无名氏') as name, nvl2(text, text, '未知') as text
  from temp1
union all
select nvl2(name, name, '无名氏') as name, nvl2(text, text, '未知') as text
  from temp2
union all
select nvl2(name, name, '无名氏') as name, nvl2(text, text, '未知') as text
  from temp3

Oracle工作中常用函数的总结_第2张图片

【c】sign(number) :  如果number大于0,sign则返回1;如果number小于0,sign则返回-1;如果number等于0,sign则返回0.

--sign(number)    如果number大于0,sign则返回1;如果number小于0,sign则返回-1;如果number等于0,sign则返回0
select sign(20 - 10), sign(10 - 20), sign(20 - 20), sign(20.0001 - 20.0000)
  from dual;

Oracle工作中常用函数的总结_第3张图片

【d】substr(str,a,b): 字符串截取函数

--str :待截取字符串
--a :截取开始位置
--b :截取个数

注意:当a为负数时,只要 |a| ≤ b,取a的个数(如:7、8、9);当 |a| ≥ b时,才取b的个数

--字符截取函数substr(str,a,b)
--str 待截取字符串
--a 截取开始位置
--b 截取个数

--注意:当a为负数时,只要 |a| ≤ b,取a的个数(如:7、8、9);当 |a| ≥ b时,才取b的个数

select substr('zhangsan', 0, 3),  --zha
       substr('zhangsan', 1, 3),  --zha
       substr('zhangsan', 3, 5),  --angsa
       substr('zhangsan', -1, 3), --n
       substr('zhangsan', -3, 2)  --sa
  from dual;

 Oracle工作中常用函数的总结_第4张图片

【e】listagg() ..within group() : 合并数据

with temp1 as
 (select '10001' as categoryId, '苹果' as categoryName from dual),
temp2 as
 (select '10001' as categoryId, '雪梨' as categoryName from dual),
temp3 as
 (select '10002' as categoryId, '铅笔' as categoryName from dual),
temp4 as
 (select '10003' as categoryId, '水果刀' as categoryName from dual),
temp5 as
 (select '10002' as categoryId, '钢笔' as categoryName from dual),
allResult as
 (select *
    from temp1
  union all
  select *
    from temp2
  union all
  select *
    from temp3
  union all
  select *
    from temp4
  union all
  select *
    from temp5)

select * from allResult;

Oracle工作中常用函数的总结_第5张图片

假如我们需要将categoryId相同的categoryName合并在一起显示,那么可以使用listagg within group函数来实现。

with temp1 as
 (select '10001' as categoryId, '苹果' as categoryName from dual),
temp2 as
 (select '10001' as categoryId, '雪梨' as categoryName from dual),
temp3 as
 (select '10002' as categoryId, '铅笔' as categoryName from dual),
temp4 as
 (select '10003' as categoryId, '水果刀' as categoryName from dual),
temp5 as
 (select '10002' as categoryId, '钢笔' as categoryName from dual),
allResult as
 (select *
    from temp1
  union all
  select *
    from temp2
  union all
  select *
    from temp3
  union all
  select *
    from temp4
  union all
  select *
    from temp5)

select t.categoryId,
       listagg(to_char(t.categoryName), ',') within group(order by t.categoryName) as categoryName
  from allResult t
 group by t.categoryId

Oracle工作中常用函数的总结_第6张图片

【f】类型转换相关函数: to_char()/to_date()/to_number()

--to_char() 将查询结果转换为字符类型

--to_number() 将字符串类型转换为数字类型
--select to_number('zhangsan') from dual;  --无效数字

--to_date() 将字符型数据转换为日期型数据

--to_char() 将查询结果转换为字符类型

--to_number() 将字符串类型转换为数字类型
--select to_number('zhangsan') from dual;  --无效数字

--to_date() 将字符型数据转换为日期型数据

select to_char(123456) as str,
       to_char(sysdate, 'YYYY-MM-DD HH24:MI:SS') as now,
       to_number('123456') as num,
       to_date('2018-11-09', 'YYYY-MM-DD') as d
  from dual;

Oracle工作中常用函数的总结_第7张图片

【g】extract(fmt from d):提取日期中的特定部分,如年、月、日等

--fmt 为:year、month、day、hour、minute、second。其中 year、month、day可以为 data 类型匹配,也可以与 timestamp 类型匹配;但是 hour、minute、second 必须与 timestamp 类型匹配。
--hour 匹配的结果中没有加上时区,在中国运行的结果小 8 小时。

--extract(fmt from d),提取日期中的特定部分。
--fmt 为:year、month、day、hour、minute、second。其中 year、month、day可以为 data 类型匹配,也可以与 timestamp 类型匹配;但是 hour、minute、second 必须与 timestamp 类型匹配。
--hour 匹配的结果中没有加上时区,在中国运行的结果小 8 小时。

select sysdate as now,
       extract(year from sysdate) as 年,
       extract(month from sysdate) as 月,
       extract(day from sysdate) as 天,
       extract(hour from systimestamp) as 小时_小8小时,
       extract(hour from systimestamp) + 8 as 小时,
       extract(minute from systimestamp) as 分钟,
       extract(second from systimestamp) as 秒
  from dual;

Oracle工作中常用函数的总结_第8张图片

【h】decode(value,if1,then1,if2,then2,if3,then3,...,else) 

(1). 匹配是否相等(当然也可以使用case when 语句实现同样效果)

with temp1 as
 (select 'female' as sex from dual),
temp2 as
 (select 'male' as sex from dual),
temp3 as
 (select '' as sex from dual),
res as
 (select sex
    from temp1
  union all
  select sex
    from temp2
  union all
  select sex
    from temp3)

--select sex from res;    


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

--用法一:匹配是否相等(当然也可以使用case when 语句实现同样效果)

--可以这样理解:
--如果 sex='female' 返回  '女'
--如果 sex='male' 返回  '男'
--否则,返回'未知'    

select sex as 性别标识,
       decode(sex, 'female', '女', 'male', '男', '未知') as 性别
  from res;

Oracle工作中常用函数的总结_第9张图片

(2). 结合sign用于比较大小
--select decode(sign(变量1-变量2),-1,变量1,变量2) from dual; --取较小值
--sign()函数根据某个值是0、正数还是负数,分别返回0、1、-1

--用法二:结合sign用于比较大小
--select decode(sign(变量1-变量2),-1,变量1,变量2) from dual; --取较小值
--sign()函数根据某个值是0、正数还是负数,分别返回0、1、-1

--取较小值/较大值
select decode(sign(99 - 88), -1, 99, 88) as min, decode(sign(99 - 88), 1, 99, 88) as max from dual;

Oracle工作中常用函数的总结_第10张图片

(3). 示例:成绩>85,显示优秀;>70显示良好;>60及格;否则是不及格。

--示例:成绩>85,显示优秀;>70显示良好;>60及格;否则是不及格。
with temp as
 (select '85' as score
    from dual
  union all
  select '80' as score
    from dual
  union all
  select '75' as score
    from dual
  union all
  select '70' as score
    from dual
  union all
  select '60' as score
    from dual
  union all
  select '55' as score
    from dual)

--select score from temp;

--实现方法一:
select score,
       decode(sign(score - 85),
              1,
              '优秀',
              0,
              '优秀',
              -1,
              decode(sign(score - 70),
                     1,
                     '良好',
                     0,
                     '良好',
                     -1,
                     decode(sign(score - 60), 1, '及格', 0, '及格', '不及格'))) as 成绩等级
  from temp;

--实现方法二:
with temp as
 (select '85' as score
    from dual
  union all
  select '80' as score
    from dual
  union all
  select '75' as score
    from dual
  union all
  select '70' as score
    from dual
  union all
  select '60' as score
    from dual
  union all
  select '55' as score
    from dual)
select score, 
       case
         when score >= 85 then
          '优秀'
         when score >= 70 then
          '良好'
         when score >= 60 then
          '及格'
         else
          '不及格'
       end as 成绩等级
  from temp;


Oracle工作中常用函数的总结_第11张图片

【i】grouping(): 在分组统计时用到,grouping只能在使用rollup或cube的查询中使用 .

grouping(xxx) 返回0或者1。如果列值为空,那么grouping()返回1;如果列值非空,那么返回0。

with temp as
 (select '10001' as depid, '12000' as salary, 'zhangsan' as n, '01' as jid
    from dual
  union all
  select '10001' as depid, '10000' as salary, 'lisi' as n, '02' as jid
    from dual
  union all
  select '10002' as depid, '1000' as salary, 'wangwu' as n, '01' as jid
    from dual
  union all
  select '10002' as depid, '2000' as salary, 'zhaoliu' as n, '03' as jid
    from dual
  union all
  select '10003' as depid, '15000' as salary, 'tianqi' as n, '01' as jid
    from dual
  union all
  select '10003' as depid, '15000' as salary, 'wangba' as n, '02' as jid
    from dual
  union all
  select '10004' as depid, '15000' as salary, 'jiudan' as n, '01' as jid
    from dual)
--select depid,sum(salary) as total from temp group by rollup(depid)

--grouping(xxx) 返回0或者1。如果列值为空,那么grouping()返回1;如果列值非空,那么返回0。grouping只能在使用rollup或cube的查询中使用    

select grouping(depid), depid, sum(salary) as total
  from temp
 group by rollup(depid);

Oracle工作中常用函数的总结_第12张图片

可见,grouping(xxx)当xxx为空的时候返回1,当xxx不为空的时候返回0.

假如我需要最后一行depid为空显示‘总计’,可以通过下面的方法实现:

with temp as
 (select '10001' as depid, '12000' as salary, 'zhangsan' as n, '01' as jid
    from dual
  union all
  select '10001' as depid, '10000' as salary, 'lisi' as n, '02' as jid
    from dual
  union all
  select '10002' as depid, '1000' as salary, 'wangwu' as n, '01' as jid
    from dual
  union all
  select '10002' as depid, '2000' as salary, 'zhaoliu' as n, '03' as jid
    from dual
  union all
  select '10003' as depid, '15000' as salary, 'tianqi' as n, '01' as jid
    from dual
  union all
  select '10003' as depid, '15000' as salary, 'wangba' as n, '02' as jid
    from dual
  union all
  select '10004' as depid, '15000' as salary, 'jiudan' as n, '01' as jid
    from dual)

--假如我需要最后一行depid为空显示‘总计’

--可见列值为空返回1,列值不为空返回0 
select decode(grouping(depid), 1, '总计', depid) as depid,
       sum(salary) as total
  from temp
 group by rollup(depid);

Oracle工作中常用函数的总结_第13张图片

另外一种实现方法:

with temp as
 (select '10001' as depid, '12000' as salary, 'zhangsan' as n, '01' as jid
    from dual
  union all
  select '10001' as depid, '10000' as salary, 'lisi' as n, '02' as jid
    from dual
  union all
  select '10002' as depid, '1000' as salary, 'wangwu' as n, '01' as jid
    from dual
  union all
  select '10002' as depid, '2000' as salary, 'zhaoliu' as n, '03' as jid
    from dual
  union all
  select '10003' as depid, '15000' as salary, 'tianqi' as n, '01' as jid
    from dual
  union all
  select '10003' as depid, '15000' as salary, 'wangba' as n, '02' as jid
    from dual
  union all
  select '10004' as depid, '15000' as salary, 'jiudan' as n, '01' as jid
    from dual)

--假如我需要最后一行depid为空显示‘总计’

--另一种方法:
select nvl(depid, '总计') as depid, sum(salary) as total
  from temp
 group by rollup(depid);
 
 

Oracle工作中常用函数的总结_第14张图片

【j】group by rollup():在分组统计并且需要小计、总结等功能时可以使用group by rollup()实现。
--rollup中列的顺序不同,则统计的结果不同。因为它是按列从右递减分组的。
--如 Group by  ROLLUP(A, B, C),首先会对(A、B、C)进行GROUP BY,然后对(A、B)进行GROUP BY,然后是(A)进行GROUP BY,最后对全表进行GROUP BY操作

我们先看看简单分组之后的结果:

with temp as
 (select '10001' as depid, '12000' as salary, 'zhangsan' as n, '01' as jid
    from dual
  union all
  select '10001' as depid, '10000' as salary, 'lisi' as n, '02' as jid
    from dual
  union all
  select '10002' as depid, '1000' as salary, 'wangwu' as n, '01' as jid
    from dual
  union all
  select '10002' as depid, '2000' as salary, 'zhaoliu' as n, '03' as jid
    from dual
  union all
  select '10003' as depid, '15000' as salary, 'tianqi' as n, '01' as jid
    from dual
  union all
  select '10003' as depid, '15000' as salary, 'wangba' as n, '02' as jid
    from dual
  union all
  select '10004' as depid, '15000' as salary, 'jiudan' as n, '01' as jid
    from dual)
select depid,sum(salary) as total from temp group by depid

Oracle工作中常用函数的总结_第15张图片

然后,加上一个 group by rolluop(depid),

with temp as
 (select '10001' as depid, '12000' as salary, 'zhangsan' as n, '01' as jid
    from dual
  union all
  select '10001' as depid, '10000' as salary, 'lisi' as n, '02' as jid
    from dual
  union all
  select '10002' as depid, '1000' as salary, 'wangwu' as n, '01' as jid
    from dual
  union all
  select '10002' as depid, '2000' as salary, 'zhaoliu' as n, '03' as jid
    from dual
  union all
  select '10003' as depid, '15000' as salary, 'tianqi' as n, '01' as jid
    from dual
  union all
  select '10003' as depid, '15000' as salary, 'wangba' as n, '02' as jid
    from dual
  union all
  select '10004' as depid, '15000' as salary, 'jiudan' as n, '01' as jid
    from dual)

--rollup指定一个列的时候,按depid分组之后有总计
--rollup中列的顺序不同,则统计的结果不同。因为它是按列从右递减分组的。
--如 Group by  ROLLUP(A, B, C),首先会对(A、B、C)进行GROUP BY,然后对(A、B)进行GROUP BY,然后是(A)进行GROUP BY,最后对全表进行GROUP BY操作
select nvl(depid,'总计'),sum(salary) as total from temp group by rollup(depid)

Oracle工作中常用函数的总结_第16张图片

可见,在rollup加上一列的时候,最后一行出现了总计。

但是,当rollup()中指定多个列的时候,按第一个的分组都会有一个小计,如下:

with temp as
 (select '10001' as depid, '12000' as salary, 'zhangsan' as n, '01' as jid
    from dual
  union all
  select '10001' as depid, '10000' as salary, 'lisi' as n, '02' as jid
    from dual
  union all
  select '10002' as depid, '1000' as salary, 'wangwu' as n, '01' as jid
    from dual
  union all
  select '10002' as depid, '2000' as salary, 'zhaoliu' as n, '03' as jid
    from dual
  union all
  select '10003' as depid, '15000' as salary, 'tianqi' as n, '01' as jid
    from dual
  union all
  select '10003' as depid, '15000' as salary, 'wangba' as n, '02' as jid
    from dual
  union all
  select '10004' as depid, '15000' as salary, 'jiudan' as n, '01' as jid
    from dual)

--rollup指定多个列的时候,按第一个的分组都会有一个小计
select decode(grouping(jid) + grouping(depid), 1, '小计', 2, '总计', jid) jid,
       depid,
       sum(salary) as total
  from temp
 group by rollup(jid, depid)

Oracle工作中常用函数的总结_第17张图片

可见,每一组Jid之后都出现了一个小计结果,最后一行也出现了总计结果,在实际工作中进行Oracle报表统计时相当有用。

但是,rollup()中指定多个列时,顺序不同,统计的结果也不同。

with temp as
 (select '10001' as depid, '12000' as salary, 'zhangsan' as n, '01' as jid
    from dual
  union all
  select '10001' as depid, '10000' as salary, 'lisi' as n, '02' as jid
    from dual
  union all
  select '10002' as depid, '1000' as salary, 'wangwu' as n, '01' as jid
    from dual
  union all
  select '10002' as depid, '2000' as salary, 'zhaoliu' as n, '03' as jid
    from dual
  union all
  select '10003' as depid, '15000' as salary, 'tianqi' as n, '01' as jid
    from dual
  union all
  select '10003' as depid, '15000' as salary, 'wangba' as n, '02' as jid
    from dual
  union all
  select '10004' as depid, '15000' as salary, 'jiudan' as n, '01' as jid
    from dual)

select decode(grouping(jid) + grouping(depid), 1, '小计', 2, '总计', depid) depid,
       jid,
       sum(salary) as total
  from temp
 group by rollup(depid,jid)

Oracle工作中常用函数的总结_第18张图片

与上面一个示例比较,这里是每一组depid对应的后面都出现了小计结果,最后出现总计结果。

二、总结

本文是笔者在实际工作中,对常用到Oracle的一些函数进行总结和一些实践,仅供大家学习参考,希望能对大家的学习有所帮助!

你可能感兴趣的:(数据库)