Oracle高级查询语句

                                                     Oracle高级查询语句
一、分组查询
1.分组函数group by :分组函数作用于一组数据,并对一组数据返回一个值
2.常用的分组函数:
  ·AVG 取平均值  ·SUM 求和  ·MIN 取最小值  ·MAX 取最大值  ·COUNT 统计次数  
  ·WM_CONCAT 行转列 如:select deptno 部门号,wm_concat(ename) 部门中员工的姓名 from emp group by deptno;
3.在分组函数中使用nvl函数
·注意:nvl函数使分组函数无法忽略空值
4.group by 语句增强
select deptno,job,sum(sal) from emp group by deptno,job;
+
select deptno,sum(sal) from emp group by deptno;
+
select sum(sal) from emp;
=
select deptno,job,sum(sal) from emp group by rollup(deptno.job);

语法:
group by rollup(a,b)
等价于:
group by a,b
+
group by a
+
group by null
(用在报表里面效果很好)
5.sqlplus报表功能
加载报表设置文档 : @+文档path 后缀.sql
例:
ttitle col 15 '我的报表' col 35 sql.pno
col deptno heading 部门号
col job heading 职位
col sum(sal) heading 工资总额
break on deptno skip 1
二、多表查询
1.笛卡尔集:笛卡尔集是多表查询的基础
笛卡尔集中的列数等于每张表中的列数之和
笛卡尔集中的行数等于每张表中的行数之和
在实际运行环境下,应避免使用笛卡尔全集,应合理使用where连接条件(连接条件至少有表的总数(n) n-1个)
2.连接的类型
·等值连接
·不等值连接
select e.empno,e.ename,e.sal,s.grade
from emp e,salgrade s
where e.sal between s.losal and s.hisal;
·外链接
核心:通过外链接,把对于连接条件不成立的记录,仍然包含在最后的结果中
左外连接:当连接条件不成立的时候,等号左边的表仍然被包含
右外连接:当连接条件不成立的时候,等号右边的表仍然被包含
select d.deptno 部门号,d.dname 部门名称,count(e.empno) 人数
from emp e,dept d
where e.deptno(+)=d.deptno
group by d.deptno,d.dname
order by d.deptno;
·自连接
核心:通过别名,将同一张表视为多张表
select e.ename 员工姓名,b.ename 老板姓名
from emp e,emp b
where e.mgr=b.empno;
自连接存在的问题:
·不适合操作大表(笛卡尔集)
·解决办法:层次查询
select level,empno,ename,sal,mgr
from emp
connect by prior empno=mgr
start with mgr is null;
或者 start with empno=7839
(connect by 上一层的员工号=老板号)
三、子查询
1.子查询需要注意的十个问题:
  ·子查询语法中的小括号
  ·子查询的书写风格
  ·可以使用子查询的位置:where,select(后面的子查询必须为单行子查询),
    having(例:select deptno,avg(sal)
                from emp
                group by deptno
                having avg(sal)>(select max(sal)
                from emp
                where deptno=30);),from
  ·不可以使用子查询的位置:group by
  ·强调:from后面的子查询
  ·主查询和子查询可以不是同一张表
  ·一般不在子查询中使用排序,但在Top-N分析问题中,必须对子查询排序
  select rownum,empno,ename,sal
  from (select * from emp order by sal desc)
  where rownum<=3;
  (rownum 行号 伪列 rownum永远按照默认的顺序生成,只能使用<,<=;不能使用>,>=)
  ·一般先执行子查询,再执行主查询;但相关子查询例外
  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);
  ·单行子查询只能使用单行操作符;多行子查询只能使用多行操作符
  单行操作符:= < <= > >= <>
  例1:select *
        from emp
        where job =(select job from emp where empno=7566)
        and sal>(select sal from emp where empno=7782);
  例2:select *
        from emp
        where sal=(select min(sal) from emp);
  例3:select deptno,min(sal)
        from emp
        group by deptno
        having min(sal)>(select min(sal)
                            from emp
                            where deptno=20);
  多行操作符:IN(等于列表中的任何一个) ANY(和子查询返回的任意一个值比较) ALL(和子查询返回的所有值比较)
  例:select *
        from emp
        where deptno in (select deptno from dept where dname = 'SALES' or dname = 'ACCOUNTING');
  例:select *
        from emp
        where sal > any(select sal from emp where deptno=30);
  例:select *
        from emp
        where sal > all(select sal from emp where deprno=30);
  ·注意:子查询中是null值的问题
  例:select *
        from emp
        where empno in(select mgr from emp);
  例:select *
        from emp
        where empno not in(select mgr from emp where mgr is not null);
 
案例一:分页查询显示员工信息:显示员工号,姓名,月薪
——每页显示四条记录
——显示第二页的员工
——按照月薪降序排列
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)
where rownum <=8)
where r>=5;

案例二:找到部门表中薪水大于部门平均薪水的员工
方法一:相关子查询
        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);
方法二:多表查询
        select e.empno,e.ename,e.sal,t.avgsal
        from emp e,(select deptno,avg(sal) avgsal from emp group by deptno) t
        where e.deptno=t.deptno and e.sal>t.avgsal;
对比:通过执行计划判断运行效率
  explain plan for + 查询语句
  select * from table(dbms_xplan.display);
  PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------
Plan hash value: 2385781174

--------------------------------------------------------------------------------
| Id  | Operation            | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |         |     1 |    43 |     8  (25)| 00:00:01 |
|   1 |  SORT AGGREGATE      |         |     1 |     7 |            |          |
|*  2 |   TABLE ACCESS FULL  | EMP     |     5 |    35 |     3   (0)| 00:00:01 |
|*  3 |  HASH JOIN           |         |     1 |    43 |     8  (25)| 00:00:01 |
|   4 |   VIEW               | VW_SQ_1 |     3 |    78 |     4  (25)| 00:00:01 |
|   5 |    HASH GROUP BY     |         |     3 |    21 |     4  (25)| 00:00:01 |

              我的报表                     2
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------
|   6 |     TABLE ACCESS FULL| EMP     |    14 |    98 |     3   (0)| 00:00:01 |
|   7 |   TABLE ACCESS FULL  | EMP     |    14 |   238 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------

  PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------
Plan hash value: 269884559

-----------------------------------------------------------------------------
| Id  | Operation            | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |      |     1 |    43 |     8  (25)| 00:00:01 |
|*  1 |  HASH JOIN           |      |     1 |    43 |     8  (25)| 00:00:01 |
|   2 |   VIEW               |      |     3 |    78 |     4  (25)| 00:00:01 |
|   3 |    HASH GROUP BY     |      |     3 |    21 |     4  (25)| 00:00:01 |
|   4 |     TABLE ACCESS FULL| EMP  |    14 |    98 |     3   (0)| 00:00:01 |
|   5 |   TABLE ACCESS FULL  | EMP  |    14 |   238 |     3   (0)| 00:00:01 |

案例三:按部门统计每年的入职员工人数
方法一:
     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;

猜你喜欢

转载自blog.csdn.net/fhy36897/article/details/89289452