(1)分组函数
包括:AVG、SUM、MIN、MAX、MAX、COUNT、WM_CONCAT
另外:NVL函数也很重要
-- NAL函数的目的是把一个空值(null)转换成一个实际的值;
-- 如果表达式1为空值,NVL返回值为表达式2的值,否则返回表达式1的值;
-- 其表达式的值可以是数字型、字符型和日期型,但表达式1和表达式2的数据类型必须相同。
NVL(表达式1,表达式2)
(2)在分组函数中使用group by
-- group by 子句,例:
select deptno ,avg(sal)
from emp
group by deptno;
-- 抽象
-- select a ,组函数(x)
-- from table
-- group by a ;
-- 在select列表中所有未包含在组函数中的列都应该包含在group by子句中,
-- 例:
select deptno ,job,sum(sal)
from emp
group by deptno, job
-- order by depton;
(3)在分组函数中使用having/where过滤分组数据
-- having子句的使用以及和where的区别
-- 1.where条件中不能使用组函数,having可以
-- 2.在输入顺序上,
-- where先过滤后分组,例:
select deptno,avg(sal)
from emp
where deptno=10
group by deptno;
-- having先分组再过滤,例:
select deptno,avg(sal)
from emp
group by deptno
having deptno=10;
-- 3.如果两个可以通用,从sql优化的角度上看,尽量使用where。where先过滤掉无关数据,对执行效率有大幅提高)
(4)在分组函数中使用order by
-- 在分组函数查询语句中进行排序,可以用order by后跟分组函数,或跟别名,或用列数字
-- 例:
select a,avg(x)
from table
group by a
order by 2 -- 或(avg(x)) 或组函数
(5)GROUP BY 语句的增强
-- GROUP BY 语句的增强,例:
group by rollup(a,b);
-- 等价于:
group by a,b + group by a + group by null
连接类别:内连接(等值连接、不等值连接)、外连接、自连接
(1)等值连接:连接条件使用等号相连
-- 查询员工编号,名字,工资,部门名称
-- 查询的内容包含两张表的内容,至少要一个条件
select e.empno,e.ename,e.sal,d.dname
from emp e,dept d -- from emp e join dept d
where e.deptno = d.deptno; -- on e.deptno = d.deptno;
-- 三表查询
select e.ename,d.dname,s.grade
from emp e,dept d,salgrade s
where e.deptno=d.deptno and e.sal between s.losal and s.hisal;
(2)不等值连接:
-- 例如:查询员工信息,要求显示:员工号,姓名,月薪,薪水级别
-- between ...and... 小值在前 大值在后
select e.empno,e.ename,e.sal,s.grade
from emp e, salgrade s -- from emp e join salgrade s
where e.sal between s.losal and s.hisal; -- on e.sal between s.losal and s.hisal;
(3)外连接: 把对于连接条件不成立的记录,仍然包含在最后的结果中
-- 例如:按部门统计员工人数,要求显示:部门号,部门名称,人数
select d.deptno 部门号,d.dname 部门名称,count(e.empno) 人数
from emp e right join dept d -- from emp e left join dept d
on e.deptno=d.deptno
group by d.deptno,d.dname;
-- 三表查询
select e.ename,d.dname,s.grade
from emp e right join dept d on e.deptno=d.deptno
left join salgrade s on e.sal between s.losal and s.hisal;
(4)自连接:通过别名,将同一张表视为多张表
-- 例如:查询员工姓名和员工老板姓名
select e.ename 员工姓名,b.ename 老板
from emp e,emp b -- 将一张表视作两张表
where e.mgr=b.empno; -- 老板的姓名=另一员工的姓名
两个查询嵌套,把其中一个select当做条件
-- 查询工资比SCOTT高的员工的工资
select *
from emp
where sal > (select sal -- 必须要有小括号
from emp
where ename='SCOTT');
子查询注意的10个问题:
(1)子查询语法中的小括号
(2)子查询的书写风格,(方便阅读
(3)可以使用子查询的位置:where,select,having,from
(4)不可以使用子查询的位置:group by
(5)强调:from 后面的子查询
(6)子查询和主查询可以不是同一张表
(7)一般不在子查询中使用排序;但在Top-N分析问题中必须对子查询排序
(8)一般先执行子查询再执行主查询;但是相关子查询例外
(9)单行子查询只能使用单行操作符;多行使用多行
(10)注意:子查询中是null的问题
-- (3)可以使用子查询的位置:where,select,having,from
-- select后面的子查询必须是一个单行子查询,即子查询结果只返回一条记录,例:
select empno,ename,sal,(select job
from emp
where empno=7839)
from emp;
-- having后面的子查询,
-- 注意这种情况不能用where代替,因为含有组函数!例:
-- 求每个部门的平均工资并且这个工资大于三十号部门工资的最大值
select deptno,avg(sal)
from emp
group by deptno
having avg(sal)> (select max(sal)
from emp
where deptno=30);
-- from后面的子查询实际上就是将子查询的结果看作一张表,例:
select * from (select empno,
ename,sal
from emp);
-- (6)主查询和子查询不是同一张表
-- 查询销售部的员工信息
-- where子查询
select *
from emp
where deptno=(select deptno from dept t where t.dname='SALES')
--多表查询(理论上更优,只有一个from,一次操作数据库)
select *
from emp e,dept d
where e.deptno=d.deptno and d.dname='SALES'
-- (7)一般不在子查询中使用排序;但在Top-N分析问题中必须对子查询排序
-- rownum是伪列,oracle默认生成行号。需要注意两个问题:
-- 行号永远按照默认的顺序生成;行号只能使用<、<=,不能使用>,>=
-- 找到员工表中工资最高的前三名
select rownum,empno,ename,sal
from (select * from emp order by sal desc)
where rownum<=3;
-- (8)一般先执行子查询再执行主查询;但是相关子查询例外
-- 主表中的某个字段作为参数传入到子查询中
-- 找出员工薪水大于本部门的平均薪水的员工
select empno,ename,sal,(select avg(sal) from emp where deptno=e.deptno) avgsal
from emp e -- 父查询中一定要使用别名
where sal > (select avg(sal) from emp where deptno=e.deptno);
-- (9)单行子查询只能使用单行操作符;多行使用多行
-- 1.单行子查询:只返回一条记录 操作符:=,>,>=,<,<=,<>不等于
例子:查询员工信息,要求:职位与7566员工一样,薪水大于7782的
select *
from emp
where job= (select job from emp where empno=7566) and
sal>(select sal from emp where empno=7782);
-- 2.多行子查询:返回多条记录。
-- 操作符:in,等于列表中的任何一个;any,和子查询返回的任意一个值作比较;all,和子查询返回的所有值比较。例子:
-- in 查询部门名称是sales和accounting 的员工信息
select *
from emp
where deptno in (select deptno from dept where dname='SALES' or dname='ACCOUNTING');
select e.*
from emp e, dept d
where e.deptno=d.deptno and (d.dname='SALES' or d.dname='ACCOUNTING');
-- any 查询工资比30号部门任意一个员工高的员工信息
select *
from emp
where sal> any ( select sal from emp where deptno=30);
select *
from emp
where sal>(select min(sal) from emp where deptno=30);
-- all 查询工资比30号部门所有一个员工高的员工信息
select *
from emp
where sal> all( select sal from emp where deptno=30);
select *
from emp
where sal>(select max(sal) from emp where deptno=30);
-- (10)子查询中是null的问题
-- not in(结果集):注意not in 后面括号里的结果集不能有空值,必须想办法过滤掉空值
-- 查询不是老板的员工:
select *
from emp
where empno not in (select mgr from emp where mgr is not null);