zoukankan      html  css  js  c++  java
  • 数据库 数据库SQL语句四

    多表查询
    等值连接
    --查询员工信息,员工号,姓名,月薪,部门名称
    select e.empno,e.ename,d.dname
    from emp e,dept d
    where e.deptno=d.deptno;
    不等值连接
    --查询员工信息,姓名,薪水,薪水级别
    select e.ename 姓名,e.sal 工资,s.grade 工资等级 from emp e,salgrade s
    where e.sal between s.losal and s.hisal
    外连接
    --按部门统计员工人数:部门号 部门名称 各部门人数
    --确定是多表查询,因为部门表中没有人数,人数和部门表有关
    --因为需要统计各个部门的人数,需要分组
    
    select e.deptno,d.dname,count(*)
    from emp e,dept d
    where e.deptno=d.deptno
    group by e.deptno,d.dname--理解:在group by之前已经形成了一个笛卡尔积的表,group by是对该表进行分组
    
    --40号部门不在笛卡尔积表中
    --我们希望把不符合条件的部门(40号部门)也要显示出来
    --希望把不满足等值条件的数据也显示出来==》外连接技术
    左连接:想把d.deptno都显示出来,把(+)写在等号右边,叫左连接
    右连接相反
    
    select d.deptno,d.dname,count(*)
    from emp e,dept d
    where e.deptno(+)=d.deptno
    group by e.deptno,d.dname
    结果显示
    DEPTNO DNAME            COUNT(*)
    ------ -------------- ----------
        10 ACCOUNTING              3
        40 OPERATIONS              1
        20 RESEARCH                5
        30 SALES                   6
    --结果分析发现40号部门竟然有一个人,但是emp表中并没有人
    --问题出现在count(*),这里*号统计的是笛卡尔积表中的数据,新拼接的笛卡尔积有一条40号部门的数据
    --这里我们应该统计emp员工表中的数据,修改count(*)===>count(e.ename)
    自连接
    --查询员工直属上司的信息,显示***的老板是**
    --思路:可以将一张表分成两张表,员工表,老板表,两张表进行笛卡尔积连接
    select a.ename||'的老板是'|| nvl(b.ename,a.ename)
    from emp a,emp b
    --where a.empno=b.mgr  错误:这种写法导致如果是员工,就无法在笛卡尔积中显示
    --where a.mgr=b.empno  这样b才是老板表,但是总老板没有显示,此时应该使用外连接技术
                           但是在哪张表上使用外连接呢?假设在老板表使用外连接,那么老板表会把所有员工信息都显示出来
                           如果在员工表使用外连接,可以把老板也显示出来
    where a.mgr=b.empno(+)
    子查询
    --对于一个问题,一步不能求解,需要多步
    --子查询的本质是select语句的嵌套
    --查询谁的工资比scott高
    --1.先求scott的工资
    --2.求比3000大的工资
    SQL> select ename from emp 
         where sal >(select sal from emp where ename='SCOTT');
    子查询的注意点:
    1.子查询要包含在括号内
    2.将子查询放在比较条件的右侧
    3.单行操作符对应单行子查询,多行操作符对应多行子查询
    子查询类型
    --单行子查询==》查询结果是一条数据
    --多行子查询==》查询结果是多条数据
    子查询知识架构(重点)
    --1.注意语法结构
    --2.子查询的()不要丢掉
    --3.主查询和子查询可以不是同一张表,只要子查询返回的结果主查询能用就行
    --4.子查询的位置
        select ...(可以放置子查询--单行子查询)
        from ...(可以放置子查询)
        where ...(可以放置子查询)
        group by ...(不能放置子查询)
        having ...(可以放置子查询)
        order by ...(不能放置子查询)
    --5.单行子查询只能用单行比较操作符(> = <)
        多行子查询只能用多行比较操作符(in ant all)
        按照子查询和主查询执行顺序来分
        一般子查询
        相关子查询
    --6.子查询返回空值问题
    --7.子查询中一般不使用order by,但是Top-N问题,子查询必须要用order by
        eg:求工资的前三名...
    解释子查询知识3--查询部门名称是SALES的员工信息
    --因为SALES在部门表中,查找部门表才能获取部门编号,接着在员工表中查询信息
    --两种实现方式--子查询或者多表查询
    select ename,deptno
    from emp
    where deptno=(select deptno from dept where dname='SALES');
    
    select e.name,e.deptno,d.dname
    from emp e,dept d
    where e.deptno=d.deptno and d.dname='SALES';
    sql优化③:子查询检索数据库两次,但是多表查询只检查数据库一次,所有优先使用多表查询,多表查询是笛卡尔积,牺牲了内存空间(因为要拼接两个表),以空间换时间
    解释子查询知识4
    --select中的子查询
    select ename,job,(select sal from emp where deptno=10) 十号部门所有工资
    from emp;
    报错:单行子查询返回多个行
    结论:select中的子查询只能是单行子查询
    
    select ename,job,(select sal from emp where deptno=10 and ename='CLARK') 十号部门所有工资
    from emp;
    执行成功
    
    --from中的子查询
    select * 
    from emp;--emp表,表就是一个集合
    
    select * from (select a,b,c from emp where d='aa');这种情况在oracle中使用比较多
    
    --查询员工号和员工姓名
    select * 
    from (select ename,empno from emp); 
    多行子查询
    --返回多行
    --使用多行比较操作符
    IN    等于列表中的任何一个
    ANY    和子查询返回的任意一个值比较
    ALL    和子查询返回的所有值比较
    --查询部门名称为SALES和ACCOUNTING的员工信息
    --多表查询
    select e.* 
    from emp e,dept d
    where e.deptno=d.deptno and d.dname in ('SALES','ACCOUNTING');
    --子查询
    select * 
    from emp
    where deptno in (select deptno from dept where dname in ('SALES','ACCOUNTING'));
    --查询薪水比30号部门 员工最低薪水要高的员工信息
    select *
    from emp
    where sal> (select min(sal) from emp where deptno=30)--单行子查询
    
    --any的使用
    select *
    from emp
    where sal> any(select sal from emp where deptno=30)--多行子查询
    --查询薪水比30号部门 所有员工薪水要高的员工信息
    select *
    from emp
    where sal> (select max(sal) from emp where deptno=30)--单行子查询
    
    --all的使用
    select *
    from emp
    where sal> all(select sal from emp where deptno=30)--多行子查询
    解释子查询知识6
    --查询不是官的员工
    --思路:先查询是经理的员工信息
    select *
    from emp
    --where empno not in (select distinct mgr from emp)--此时因为有空值,所以无法得出正确结果
    where empno not in (select distinct mgr from emp where mgr is not null)--进行过滤空值
    
    in和not in与空值null的本质理解
    空值参与任何运算都是空值
    deptno in (10,20,null)
    相当于deptno=10||deptno=20||deptno=null;这是或的关系,就算有空值也不影响结果
    deptno not in (10,20,null)
    相当于 deptno!=10&&deptno!=20&&deptno!=null;这是与的关系,有一个为空,整个结果就是假
    解释子查询知识7
    --有关oracle伪列 rownum的说明
    1.rownum是oracle的数据字典,rownum的生成按照oracle的默认顺序生成,每一个结果集都有相应的rownum
    2.rownum只能使用<功能,不能使用>或者>=功能例如where rownum>3;这是错误的
    
    --查找员工表中工资最高的前三名
    select rownum,empno,ename,sal
    from
    (select rownum r,empno,ename,sal from emp 
     order by sal)
    where rownum<=3
    --注释:每一个结果集都有相应的rownum,所以本SQL语句中的两个集合分别有两个rownum,并且各不相同
    oracle的分页
    --按照员工薪水,降序,求第二页数据(每页4条数据)
    --第一步:获取所有数据,降序排列
    select empno,ename,sal
    from emp
    order by sal desc
    --第二步:以第一步的集合获取前8条数据(因为是第二页,每页四条,并且rownum只能使用<select rownum,empno,ename,sal
    from (
        select empno,ename,sal
        from emp
        order by sal desc
    )
    where rownum<=8
    --第三步:以第二步集合为基础查询第二页数据,每个查询结果集都有一个rownum,并且rownum不可以使用>
              但是如果我将这个数据集作为源数据,再查询一遍,那么源数据中的rownum就会变成一个列名,
              不再是oracle的数据字典,这样就可以做>操作
    select r,empno,ename,sal--这里的r是第二步源数据集合中的r,之所以取别名是因为rownum是oracle的数据字典,防止冲突
    from (
        select rownum r,empno,ename,sal
        from (
            select empno,ename,sal
            from emp
            order by sal desc
        )
        where rownum<=8
    )
    where r>=5;
    
    oracle分页总结--内层排序,外层选择
    综合案例
    --找到员工表中薪水大于本部门平均薪水的员工
    方案一:
    --分析:结果是员工信息
    --各部门因此需要分组,分组求出部门号和部门平均工资
    --将上一步数据当作一个集合,与原表进行多表查询
    select e.ename,e.sal,r.avgsal
    from emp e, (
    select deptno,avg(sal) avgsal
    from emp
    group by deptno
    ) r
    where e.deptno=r.deptno and e.sal>r.avgsal
    
    方案二(相关子查询)
    --相关子查询:主查询中的参数 通过 别名的方式,传给子查询
    select deptno,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)
  • 相关阅读:
    sql number类型和varchar2类型
    B
    E
    D
    B
    A
    第三课 选区
    第二课 新建文件与图层
    第一课 界面认识
    CSS命名规则
  • 原文地址:https://www.cnblogs.com/zhanggaofeng/p/6264047.html
Copyright © 2011-2022 走看看