【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
【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
【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;
【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;
【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;
假如我们需要将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
【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;
【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;
【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;
(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;
(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;
【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);
可见,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);
另外一种实现方法:
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);
【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
然后,加上一个 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)
可见,在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)
可见,每一组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)
与上面一个示例比较,这里是每一组depid对应的后面都出现了小计结果,最后出现总计结果。
本文是笔者在实际工作中,对常用到Oracle的一些函数进行总结和一些实践,仅供大家学习参考,希望能对大家的学习有所帮助!