Oracle高级查询

1.host cls清除SQL plus上的文字。

2.使用avg()平均数 sum()总和。

    select avg(sal),sum(sal) from emp;--求工资的平均数和总和。

3.max()最大值,min()最小值

    select max(sal),min(sal) from emp;--求工资的最大值和最小值。

4.count()总的记录数

     select count(deptno) from emp;--求emp表的总记录数。

     select count(distinct deptno) from emp;--去除empno的重复查出总记录数。

5.vw_concat()行转列

    select deptno 部门号,wm_concat(empno)姓名 from emp group by deptno;--通过部门编号进行分组行转列查询

6.nvl(?,?)如果第一个为null ,结果就是第二个,否则就是第一个

    select sum(comm)/count(*) 一,sum(comm)/count(comm) 二,avg(comm) 三 from emp;

    --三种方式求奖金的平均数 (第一种分母为14)(其他的都是4)

    结果:        一         二         三
                ---------- ---------- ----------
       157.142857        550        550

    select sum(comm)/count(*) 一,sum(comm)/count(nvl(comm,0)) 二,avg(comm) 三 from emp;

    结果:            一         二         三
                    ---------- ---------- ----------

                157.142857 157.142857        550

7.group by 分组查询

   在select 列表中所有未包含在组函数中的列都应该包含在group by子句中

   select a,b,c,组函数(x) from 表名 group by a,b,c;

    --通过部门进行分组,求平均薪水--
    select deptno,avg(sal) from emp group by deptno
    --通过部门号排序,通过部门,工作分组查询总工资

    select deptno,job,sum(sal) from emp group by deptno,job order by deptno;

    --通过部门分组查询部门的平均工资过滤平均工资小于200的部门---

    select deptno,avg(sal) from emp group by deptno having avg(sal)>2000

8.having和where的区别

    having用于分组函数,where不能用于分组函数,某些情况下作用是一样的

    select deptno,avg(sal) from emp having deptno=10 group by deptno;

    select deptno,avg(sal) from emp where deptno=10 group by deptno;

    where条件不能有分组函数

    例:select deptno,avg(sal) from emp where avg(sal)>2000 group by deptno;

    sql优化尽量使用where因为where的效率更高where先过滤后分组。比如员工表共有1亿条数据要查询编号为10的员工(共10     人)where先过滤出这10个人然后进行分组,having先分组,在过滤。

9.group by 增强

    group by rollup(a,b)= group by rollup a,b+group by a+group by null;

    select deptno,job,sum(sal) from emp group by rollup(deptno,job);

10.内连接,左连接,右连接,笛卡尔乘积

    ------内连接查询-------
    select a.*,b.* from emp a inner join dept b on a.deptno=b.deptno;
    ------左连接------
    select a.*,b.* from emp a left outer join dept b on a.deptno=b.deptno;
    ------右连接------
    select a.*,b.* from emp a right join dept b on a.deptno=b.deptno;

    笛卡尔乘积

    select a.*,b.* from emp a,dept b;

   11. --自链接查询 老板编号等于员工编号 不适合操作大表,笛卡尔乘积太大---
    select e.ename 员工姓名,b.ename 老板姓名 from emp e,emp b where e.mgr=b.empno;
    --层次查询--connect by相当于where prior上一层的 start whit empno=7839 --就相当于start with mgr is null--
    select level,empno,ename,sal,mgr 
    from emp 
    connect by prior empno=mgr start with mgr is null 

    order by level;

12.--子查询:一个select嵌套一个select--

    select * from emp where sal>(select sal from emp where ename='SCOTT');


    --可以使用子查询的位置--where,select,having,from--
    --SELECT 后面的子查询只能是单行子查询(结果只有一行)
    select empno,ename,sal,(select job from emp where empno=7369) 第四列 from emp;


    --having--查询部门平均薪资大于30号部门的最大工资的部门和平均薪资--
    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 from emp);


    --不可以在group by子句后出现子查询--


    --主查询和子查询不在同一张表中--只要子查询的结果可以用于主查询就没问题
    select * from emp where deptno=(select deptno from dept where dname='SALES')
    --另一种方法,多表查询--

    select e.* from emp e,dept d where e.deptno=d.deptno and d.dname='SALES';

    --子查询,排序--rownum只能用<= 不能用>=--
                      --通过薪资降序--取前三行

    select rownum,empno,sal from (select * from emp order by sal desc)where rownum<4

    --相关子查询--找出员工表中员工工资大于部门平均薪资的员工--
    select empno,ename,sal,(select avg(sal) from emp where deptno=e.deptno) 部门平均薪资
       from emp e where 
       sal>(select avg(sal) from emp where deptno=e.deptno)

    --单行子查询--查询员工信息,职位与7566员工一样,薪水大于7782.
    select * 
    from emp 
    where job=(select job from emp where empno=7566) and 

      sal>(select sal from emp where empno=7782);

    --查询工资最低的员工信息--
    select *
    from emp

    where sal=(select min(sal) from emp)

    --多行子查询 查询最低工资大于20号部门最低工资的部门号和部门的最低工资
    select deptno,min(sal) 
    from emp group by deptno
    having min(sal)>(select min(sal) 
                                 from emp 

                                 where deptno=20);

    --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) 

    --单行子查询和多行子查询中有null值的解决办法--
    select * from (select * from emp where ename='tom')
    --多行子查询有null值--查询不是老板的员工

    select * from emp where empno not in (select mgr from emp where mgr is not null)

13.案例1 ,通过薪资降序,分页查找5-8条数据

    select rownum, r,empno,ename,sal 
    from(select rownum r,empno,ename,sal
             from(select rownum,empno,ename,sal 
                      from emp order by sal desc) e1 
             where rownum<=8) e2

    where r>4;

    案例2.查找emp 表中员工薪水大于本部门平均薪水的员工--

             --相关子查询--

    select empno,ename,sal,(select avg(sal) 

    from emp where deptno=e.deptno) 部门平均薪水,deptno

                     from emp e

                     where sal>(select avg(sal) 

                                        from emp 

                                        where deptno=e.deptno)

    --多表联查--

    select e.empno,e.ename,e.sal,d.avgsal
    from emp e,(select deptno,avg(sal) avgsal from emp group by deptno) d

    where e.deptno=d.deptno and e.sal>d.avgsal;

    explain plan for +sql语句 运行执行计划

    select * from table(dbms_xplan.display); 查看运行计划

    案例3.查询1980年入职的人数1981年入职的人数1982年入职的人数,1987年入职的人数  这四年入职的总人数total表示。

    使用函数解决

    select count(*) Total,
       sum(decode(to_char(hiredate,'yyyy'),'1980',1,0)) "1980",
       sum(decode(to_char(hiredate,'yyyy'),'1981',1,0)) "1981",
       sum(decode(to_char(hiredate,'yyyy'),'1982',1,0)) "1982",
       sum(decode(to_char(hiredate,'yyyy'),'1987',1,0)) "1987"

    from emp

    使用子查询解决

    select
           (select count(*) from emp) Total,
           (select count(*) from emp where to_char(hiredate,'yyyy')='1980') "1980", 
           (select count(*) from emp where to_char(hiredate,'yyyy')='1981') "1981",
           (select count(*) from emp where to_char(hiredate,'yyyy')='1982') "1982",
           (select count(*) from emp where to_char(hiredate,'yyyy')='1987') "1987"

    from dual;

14.练习

    一张学生表 两个字段 id sname

    一张选课表 两个字段 主键 sc_id cid关联学生的id

    create table student(
           id number (9) primary key,
           sname varchar2(20)
    ) 
    create table sclass(
           sc_id number (9)primary key,
           cid varchar2(100) 

    )

    显示结果

    

    sql语句

    select sc.sc_id,wm_concat(sname) 
    from student s,sclass sc 
    where instr(sc.cid,s.id)>0

    group by sc.sc_id

    解释:instr返回字符或字符串在另一个字符串中第一次出现的位置

              wm_concat行转列

猜你喜欢

转载自blog.csdn.net/qq_40529747/article/details/79819096