oracle 空值替换6,Oracle 查询优化改写

第一章 单表查询

第二章 给查询结果排序

第三章 使用数字

第四章 操作多个表

第一章 单表查询

1、将空值转换为实际值

SELECT coalesce(comm,0) FROM emp;

说明coalesce与nvl、decode的区别

①coalesce(comm,0),若comm为空,则取0,否则返回comm;

适合多个参数,coalesce(EXPR1,EXPR2,EXPR3,…,EXPRn),所有参数类型必须保持一致;

coalesce可返回第一个不为空的值。

②nvl(comm,0)只适合2个参数;将空值转换为0;

③decode(comm,’apple’,0),若comm=apple,返回0,否则返回NULL

2、拼接列

用字符串“||”把各列连在一起

SELECT ename ||'的工作是'||job AS msg FROM emp WHERE deptno = 10;

——————————————————

CLARK的工作是MANAGER

3、限制返回的行数

SELECT *

FROM (SELECT rownum AS an,emp.* FROM emp WHERE rownum <=2)

WHERE sn = 2;

本语句返回的是第二行的数据,但是为什么先要写子查询呢?

因为rownum是依次对数据做标识的,需要先把所有的数据取出来,才能确认第二行。

4、随机返回n条记录

SELECT empno,ename

FROM (SELECT empno,ename FROM emp ORDER BY dbmsandom.value())

WHERE rownum <= 3;

为什么要写一层嵌套?

对于随机返回n行数据,正确的写法应该是 先随机排序,再取数据 。否则每次随机返回的值会是一样的。

第二章 给查询结果排序

1、将返回结果排序

ORDER BY 1,2;

表示按照SELECT后的字段进行排序,1表示第一栏,2表示第二栏;

此处的意思是,先按照第一栏升序排列,在第一栏相同的情况下,按第二栏升序排列。

2、TRANSLATE

#语法格式

TRANSLATE(expr,from_string,to_string)

from_string 与 to_string 一一对应,如果在from_string中没有的,就不变。

如果to_string 为空,则返回空值;

如果to_string 对应的没有字符,删除from_string中列出的字符将会被消掉。

SELECT TRANSLATE('ab你好bcadefg','1abcdefg','1')AS NEW_STR FROM DUAL;

NEW_STR

------

你好

“你好”不进行替换,其他字符对应位置均为空,故替换为空

3、处理排序空值

用 关键字NULLS FIRST 和NULLS LAST

空值在前 NULLS FIRST

空值在后 NULLS LAST

第三章 使用数字

1、正确的平均值

avg(coalesce(comm,0)) /需要把空值转换为0/

聚合函数会忽略空值,对avg,count会产生影响,根据需求决定把空值转换为零。

2、group by

如果select 后面有聚合函数,通常需要加group by;

当表中没有数据时, 不加group by会返回一行数据,但加了group by 会没有数据返回。

3、计算累计差

可将需要减的数,先变成负数,用CASE WHEN

4、dense_rank()

返回排序值,若有相同值,可都返回

dense_rank() over(PARTITION BY deptno ORDER BY sal DESC)

5、计算出现次数最多的值

比如查看部门中哪个工资等级的员工最多,需要分4步进行

SELECT deptno,sal

FROM(select deptno,sal

dense_rank() over(PARTITION BY deptno ORDER BY 出现次数 DESC) 次数排序

FROM (SELECT sal,deptno,count(*) 出现次数

FROM emp

GROUP BY deptno,sal)x)y

where 次数排序 = 1;

第一步:计算不同工资出现的次数

第二步:按次数排序生成序号

第三步:根据序号过滤得到需要的结果

第四步:利用partition by 子句分别查询各部门哪个工资等级的员工最多

6、返回最值所在行数据

①标量–先取出最大值,再与此最大值关联,略麻烦

SELECT deptno,

empno,

(SELECT MAX(b.ename) FROM emp b WHERE b.sal = a.max_sal)工资最高的人,

ename,

sal

FROM (SELECT deptno,

empno,

MAX(sal) over (PARTITION BY deptno) max_sal,

ename,

sal

FROM emp a

WHERE deptno = 10)a

ORDER BY 1,5 DESC;

②分析函数

SELECT deptno,

empno,

MAX(ename)keep(dense_rank FIRST ORDER BY sal)over (PARTITION BY deptno) 工资最低的人,

MAX(ename)keep(dense_rank LAST ORDER BY sal)over (PARTITION BY deptno) 工资最高的人,

ename,

sal

FROM emp

WHERE deptno = 10

ORDER BY 1,6 DESC;

KEEP函数可以满足此要求,且可同时返回最大值和最小值;

另外,frist、last语句也可放在group 里与其他聚合函数一样使用,这时要去掉后面的over (partition by **)

7、求总和的百分比

总工资合计需要用到分析函数:sum()和over()

当over()后不加任何内容时,就是对所有的数据进行汇总。

SELECT deptno 部门,

工资合计,

总合计,

round((工资合计/总合计)*100,2) 工资比例

FROM (SELECT deptno,工资合计,SUM(工资合计) over() 总合计

FROM(SELECT deptno,SUM(sal) 工资合计 FROM emp GROUP BY deptno)x)y

ORDER BY 1;

第一步:分组汇总

第二步:通过分析函数获取总合计

第三步:得到总合计周就可以计算比例

另外,可以用专用的比例函数“ratio_to_report”来直接计算

SELECT deptno,

empno,

ename,

sal,

round(ratio_to_report(sal) over(PARTITION BY deptno)*100,2) 工资比例

FROM emp

ORDER BY 1,2;

第四章 操作多个表

1、union all与空字符串

union all常用来于合并多个数据集,空字符串本身是varchar2类型,null可以是任何类型,故二者不等价。

2、union 与or

将or语句进行改写,如果改写成union all结果就是错的,因为 or是两个结果的合集而不是并集,故改写时需要改为union来去掉重复的数据。

*但是!*不仅2个 数据集间重复的数据会被去重,而且单个数据集里面重复的数据也会被去重,有重复数据集用UNION后得到的数据与预期会不一致。

所以,需要在去重前加一个可以唯一标识各行的列即可。

加入唯一列,既可保证正确的去重,也可防止不该发生的去重。

除了用唯一列、主键列外,还可以用rowid。

还可以增加rownum来当做唯一列。

3、组合相关的列

当有多个表关联时,join的方式更能清楚的看清各表之间的关系,建议优先使用JOIN的写法。

4、IN、EXISTS和 INNER JOIN

此3种写法并没有固定的哪种写法更高效,在写的时候,需要查看PLAN。

5、INNER JOIN、LEFT JOIN 、RIGHT JOIN、FULL JOIN

INNER JOIN返回2个表匹配的数据;

LEFT JOIN只返回与左表匹配的数据;

select 1.str left_str,r.str right_str

from 1,r

where 1.v=r.v(+)

order by 1,2;

--以1为基准表,返回2中与1匹配的数据

RIGHT JOIN返回与右表匹配的数据;

select 1.str left_str,r.str right_str

from 1,r

where 1.v(+)=r.v

order by 1,2;

--以2为基准表,返回1中与r匹配的数据

FULL JOIN无(+)的写法;该方式均返回所有的数据,但只有相匹配的数据显示在同一行, 非匹配的行只显示一个表的数据。

6、自关联

自关联的话,其实就是2次查询同一个表,但是取不同的别名。用JOIN连接。

7、检查两个表中的数据及对应数据的条数是否相同

比较2个数据集的不同时,通常用类似下面的FULL JOIN语句

SELECT v.empno,v.ename,b.empno,b.ename

FROM v

FULL JOIN emp b ON (b.empno = v.empno)

WHERE (v.empno IS NULL OR b.empno IS NULL)

有时需要对数据进行处理,再进行比较,比如上述语句再加一列显示相同数据的条数,再进行比较。

SELECT v.empno,v.ename,v.cnt,emp.empno,emp.ename,emp.cnt

FROM (SELECT empno,ename,COUNT(*) cnt FROM v GROUP BY empno,ename)v

FULL JOIN (SELECT empno,ename,COUNT(*) cnt FROM emp GROUP BY empno,ename)emp

ON (emp.empno = v.empno AND emp.cnt = v.cnt)

WHERE (v.empno IS NULL OR emp.empno IS NULL)

8、聚集与内连接

*有点没看懂,改天更

9、聚集与外连接

先做聚集操作,再外连接即可。

SELECT e.deptno,

SUM(e.sal) total_sal,

SUM(e.sal * eb2.rate) total_bonus

FROM emp e

LEFT JOIN(SELECT eb.empno,

SUM(CASE

WHEN eb.type = 1 THEN

0.1

WHEN eb.type = 2 THEN

0.2

WHEN eb.type = 3 THEN

0.3

END) rate

FROM emp_bonus eb

GROUP BY eb.empno)eb2 ON eb2.empno = e.empno

GROUP BY e.deptno

ORDER BY 1;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值