Oracle中select函数以及分组多表连接等重要点以及示例

Oracle中select函数以及分组多表连接等重要点

函数

–函数

–内置函数和自定义函数

–单行函数:一条记录返回一个结果的

–多行函数|组函数|聚合函数:多条记录返回一条结果的

单行函数

单行函数:一条记录返回一个结果的

示例:


--单行函数

--当前时间
select distinct sysdate from emp;
select sysdate from dual;
select current_date from dual;

--加减时间
--2天以后
select sysdate+2 from dual;

--所有员工入职的3天前是几号
select hiredate,hiredate-3 from emp;

--查询所有员工的使用期期到期(转正的日期)3个月试用期
select hiredate,add_months(hiredate,3) from emp;--add_month(日期对象,月份数)

--查询所有员工到目前为止一共工作了几个月
select hiredate,months_between(sysdate,hiredate) from emp;--months_between(大的月份,小的月份)

--查询当前月的最后一天
select last_day(current_date) from dual;--last_day(日期对象)

--下一个星期三是几号(即将要过的星期三)
select next_day(sysdate,'星期三') from dual;--next_day(当前时间,下个星期几)

--to_date(数据,格式)
--to_cahr(数据,格式)
--设定一个特定的时间(用一个特定的时间字符串转换为日期)
--设定一个时间   就是今天'2018-9-5 16:18:25'
select to_date('2018-9-5 16:18:25','yyyy-mm-dd hh24:mi:ss')+3 from dual;

--将日期转为特定格式的字符串
select to_char(sysdate,'yyyy"年"-mm"月"-dd"日" hh12:mi:ss') from dual;

--给每个部门后面添加一个伪列,如果10部门,伪列显示为十,二十,三十...
--判定函数 decode(判断字段,值1,结果1,值2,结果2,...(,默认结果))
select deptno,dname,loc,decode(deptno,10,'十',20,'二十',30,'三十','四十') 中文部门编号 from dept;


--给20部门的所有员工都涨薪资10%,显示出员工的名称,原来的薪水,所属部门编号,涨薪后的薪水
select ename,sal,deptno,decode(deptno,20,sal*1.1)涨薪后 from emp;

--10部门涨薪资10%,20部门涨薪资20%,30部门降薪1%,40部门薪资翻3倍
select ename,sal,(case deptno when 10 then sal*1.1 when 20 then sal*1.2 when 30 then sal*0.99 when 40 then sal*3 end)涨薪后 from emp;

组函数

多行函数|组函数|聚合函数:多条记录返回一条结果的

–组函数|聚合函数|多行函数:对结果集进行组函数计算

–多行记录返回一个结果

–count(条件) sum(条件) max() min() avg()

–注意:组函数不能和非分组字段一起使用

示例:


--统计一下一共有多少个员工
select count(empno) from emp;
select count(*) from emp;
select count(1) from emp;--伪列   相当于为每条数据的后面添加一个伪列字段 1

--统计一共有几个部门
select count(*) from dept;


--统计有员工存在的部门总数
select count(distinct deptno) from emp;


--统计20部门一共有多少人
select count(deptno) from emp where deptno=20;


--计算本公司每个月一共要在工资上花多少钱
select sum(sal) from emp;


--计算20部门每个月的工资花销
select sum(sal) from emp where deptno=20;


--查询本公司的最高工资和最低工资
select max(sal),min(sal) from emp;


--查询30部门的最高工资和最低工资
select max(sal),min(sal) from emp where deptno=30;


--avg 平均工资
select avg(sal) from emp;


--请查询出20部门的平均工资
select avg(sal) from emp where deptno=20;


--计算出所有员工的奖金总和
select sum(comm) from emp where comm is not null;

--统计一共有多少个员工null 不参与运算
--统计有奖金的员工有几个
select count(comm) from emp;

--查询最高薪水的员工姓名,以及薪水
select max(sal) from emp;
select ename from emp where sal in(select max(sal) from emp);


--查询工资低于平均工资的员工编号、姓名以及工资
select empno,ename,sal from emp where sal<(select avg(sal) from emp);

--查询比SMITH薪资高并且是同一个部门的员工信息
select * from emp where (select sal from emp where ename='SMITH')<sal and (select deptno from emp where ename='SMITH')=deptno;
--查看高于本部门平均薪水员工姓名
select ename from emp e1 where sal>(select avg(sal) from emp e2 where e1.deptno=e2.deptno);

分组

–分组:group by 分组字段

–查询公式:select 数据 from 数据来源 where 条件 group by 分组字段1,… having 过滤组信息(以组为单位过滤) order by 排序字段 …;

–执行流程:from – where – group by – having – select
– order by

–注意:

– 1、select后如果出现了组函数|分了组,组函数不能与非分组字段使用,可以与其他组函数|分组字段一起使用

– 2、where后不能使用组函数 因为还没有组,执行流程问题

– 3、如果一点使用分组,select后面只能为分组字段,或者组函数

示例:


--求出所有员工存在的部门编号
select deptno from emp group by deptno;

--找出20部门和30部门的最高工资
select max(sal) from emp where deptno in(20,30);
--找出20部门和30部门中每个部门的最高工资
select max(sal),deptno from emp where deptno in(20,30) group by deptno;--先过滤 后分组
select max(sal),deptno from emp group by deptno having deptno in(20,30);--先分组 后过滤
--求出每个部门的平均工资
select avg(sal),deptno from emp group by deptno;

--求出每个部门员工工资高于1000的部门平均工资
select avg(sal) from emp where sal>1000 group by deptno;

--求出10和20部门部门的那些工资高于1000的员工的平均工资
select avg(sal) from emp where sal>1000 group by deptno having deptno in(10,20);
--不推荐使用,效率比上面的低
select * from (select avg(sal),deptno from emp where sal>1000 group by deptno) where deptno in(10,20);

--找出每个部门的最高工资
select max(sal),deptno from emp group by deptno;

--求出每个部门的平均工资高于2000的部门编号和平均工资
select deptno,avg(sal) from emp group by deptno having avg(sal)>2000;
select * from (select deptno,avg(sal) avg1 from emp group by deptno) where avg1>2000;--组函数起别名可以用

--按部门岗位查询平均工资
select avg(sal) from emp group by job;

--按岗位查询平均工资,且平均工资大于2000的岗位
select avg(sal) from emp group by job having avg(sal)>2000;

--查询最低平均工资的部门编号
select deptno from (select deptno,avg(sal) avg2 from emp group by deptno) where avg2=(select min(avg(sal)) from emp group by deptno);

--统计每个部门的员工数
select count(deptno) from emp group by deptno;

--查询平均工资在1500到2000之间的部门平均工资和部门编号
select deptno,avg(sal) from emp group by deptno having avg(sal) between 1500 and 2000;

--查询工资高于20部门平均工资的员工
select ename,sal from emp where sal>(select avg(sal) from emp where deptno=20);

--不行 where中不能使用select后字段别名,因为执行流程的原因,先走from,走到where时还没有别名
--select ename name,empno from emp where name='SMITH';    错误

子查询和行转列

通过decode函数可以做到行转列
示例:


--使用一条语句,查询每门课程都大于80分的学生姓名
select name
  from tb_student
 group by name
having count(distinct course) = (select count(distinct course)
                                   from tb_student) and min(score) > 80;
--一共有几门课程
select count(distinct course) from tb_student;
--每个人的最低分
select min(score),name from tb_student group by name;

--行转列
select name,
       min(decode(course, '语文', score)) 语文,
       max(decode(course, '数学', score)) 数学,
       min(decode(course, '英语', score)) 英语
  from tb_student
 group by name;

分页

通过rownum可以做到分页

–rowid 和 rownum 都是伪列

–rowid理解为记录在插入到数据库的表中时候就存在的数据的地址(对象地址),其实不是地址,根据地址得到的值

–如果一个表中没有主键,没有不可重复的字段,可能会出现多条一模一样的数据,无法区分重复数据,可以根据rowid进行区分

–select 数据 from 数据来源 where 行过滤条件 group by 分组字段 having 组过滤信息 order by 排序

–执行流程: from – where – group by – having – select – order by

在oracle中使用rownum因为rownum规律可循,控制rownum序号从1开始,每次+1,方便判断

示例:


--rowid 和 rownum 都是伪列
--rowid理解为记录在插入到数据库的表中时候就存在的数据的地址(对象地址),其实不是地址,根据地址得到的值
--如果一个表中没有主键,没有不可重复的字段,可能会出现多条一模一样的数据,无法区分重复数据,可以根据rowid进行区分


--select 数据 from 数据来源 where 行过滤条件 group by 分组字段 having 组过滤信息 order by 排序
--执行流程: from -- where -- group by -- having -- select -- order by

select deptno,dname,loc,rowid from dept;

select empno,ename,rowid from emp;

--当一个表中有多条一模一样的数据的时候,实现去重,重复数据只保留一条

/*insert into tb_student values(1,'张三','语文',81);
insert into tb_student values(2,'张三','数学',75);
insert into tb_student values(3,'李四','语文',81);
insert into tb_student values(4,'李四','数学',90);
insert into tb_student values(5,'王五','语文',81);
insert into tb_student values(6,'王五','数学',100);
insert into tb_student values(7,'王五','英语',90);*/

select * from tb_student;

--查到要保留的数据
select id,name,course,score,min(rowid) from tb_student group by id,name,course,score;

select * from tb_student where rowid in(select min(rowid) from tb_student group by id,name,course,score);

--查到要删除的数据
select * from tb_student where not rowid in(select min(rowid) from tb_student group by id,name,course,score);

--删除这些重复的数据
delete from tb_student where not rowid in(select min(rowid) from tb_student group by id,name,course,score);

--rownum 结果集的序号 有一个结果集就有一个rownum select查到的结果集 从1开始,每次+1
select deptno,dname,loc,rowid,rownum from dept;
select empno,ename,deptno,sal,comm,mgr,rowid,rownum from emp;

--分页:在oracle中使用rownum因为rownum规律可循,控制rownum序号从1开始,每次+1,方便判断
--查询
--先排序后确定rownum
select deptno,dname,rownum from dept order by deptno desc;--根据主键字段排序
--先确定rownum再排序
select deptno,dname,rownum from dept order by loc;--根据非主键字段排序


--保证一定先排序后确定rownum,在结果集的外面嵌套一层select,这个select的rownum肯定就是从1开始,根据这个有规律的,已经确定的rownum进行判断操作就可以了
select deptno,dname,rownum from dept order by loc;
select rownum,deptno,dname,num from (select deptno,dname,rownum num from dept order by loc);


select empno,ename,sal,comm,rownum from(select empno,ename,sal,comm,rownum from emp order by sal desc);


--分页:
--i页数 num每页显示几个
--num=3 i=4
--每一页要显示的数据的rownum            第一个 rownum>=num*(i-1)+1        最后一个:row<=num*i
select *
  from (select empno, ename, sal, comm, rownum row2
          from (select empno, ename, sal, comm, rownum
                  from emp
                 order by sal desc))
 where row2 >= 3 * (1 - 1) + 1
   and row2 <= 3 * 1;
   
   
--查询20和30部门员工,按照工资进行升序排序,实现分页,查询第3页i的数据,每页显示2个 num
select ename,empno,sal,rownum from emp where deptno in(20,30) order by sal asc;
select ename,empno,sal,rownum from (select ename,empno,sal,rownum from emp where deptno in(20,30) order by sal asc);

select ename, empno, sal
  from (select ename, empno, sal, rownum n
          from (select ename, empno, sal, rownum
                  from emp
                 where deptno in (20, 30)
                 order by sal asc))
 where n >= 2*(3-1)+1
   and n <= 2*3;

表连接

–当要查询的数据来自于不同的表,需要实现多表联查

–92语法 99 语法

–内连接:有where 满足条件才显示,不满足不显示

–外链接:左外连接|左连接 右外连接|右连接
主表在逗号的左边就是左连接,在逗号的右边就是右连接

–主表:主表中的数据无论是否满足连接条件都要显示

–查询有上级的员工信息,以及这个员工的上级信息

–92语法 select 数据 from 表1,表2,表3…;

示例:


--笛卡尔积  对乘效果
select * from emp,dept;
--等值连接
select empno,ename,emp.deptno from emp,dept where emp.deptno=dept.deptno;--注意:当使用同名字段的时候,需要指明字段出处

--非等值连接
--查询员工信息以及每个员工的薪资等级
select empno,ename,sal,grade from emp,salgrade where emp.sal between losal and hisal;
--2500这个薪资在几等级
select grade from salgrade where 2500 between losal and hisal;

--自连接
--查询有上级的员工信息,以及这个员工的上级信息
select * from emp e1,emp e2 where e1.mgr=e2.empno;

--外链接:左外连接|左连接    右外连接|右连接  主表在逗号的左边就是左连接,在逗号的右边就是右连接
--主表:主表中的数据无论是否满足连接条件都要显示
--查询有上级的员工信息,以及这个员工的上级信息

select * from emp e1,emp e2 where e1.mgr=e2.empno(+);--左连接,根据主表位置确定 e1
select * from emp e2,emp e1 where e1.mgr=e2.empno(+) and  e1.deptno in(10,20) order by e1.empno desc;--右连接,根据主表位置确定 e1


--找出30部门的员工名称以及部门名称
select ename,dname,emp.deptno from emp,dept where emp.deptno=30 and emp.deptno=dept.deptno;
--找出所有部门的员工数以及部门名称
select dname,count(empno) from emp,dept where emp.deptno(+)=dept.deptno group by dname;
select dname,c 人数 from dept d,(select deptno,count(1) c from emp group by deptno) e where d.deptno=e.deptno;

--先把没一个部门的部门编号和部门人数求出
select deptno,count(1) from emp group by deptno;

--上面这个结果集与部门表进行连接
select dname,nvl(c,0) 人数 from dept d,(select deptno,count(1) c from emp group by deptno) e where d.deptno=e.deptno(+);


--找出所有员工的部门名称以及员工数
select dname,count(1) from emp,dept where emp.deptno=dept.deptno group by dname;



--查询所有员工的信息,以及所在的部门信息
select * from emp,dept where emp.deptno=dept.deptno(+);


--查询员工信息,部门信息,薪资等级,上级信息
select dname 部门名称, e1.ename 员工名称, grade 薪资等级, e2.ename 上级名称
  from emp e1, emp e2, dept d, salgrade s
 where e1.deptno = d.deptno
   and e1.sal between losal and hisal
   and e1.mgr = e2.mgr;

发布了17 篇原创文章 · 获赞 17 · 访问量 2707

猜你喜欢

转载自blog.csdn.net/Rabbit_white_/article/details/104188277