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)
  • 相关阅读:
    Linux内核网络协议栈优化总纲
    Java实现 蓝桥杯VIP 算法训练 连续正整数的和
    Java实现 蓝桥杯VIP 算法训练 连续正整数的和
    Java实现 蓝桥杯VIP 算法训练 寂寞的数
    Java实现 蓝桥杯VIP 算法训练 寂寞的数
    Java实现 蓝桥杯VIP 算法训练 学做菜
    Java实现 蓝桥杯VIP 算法训练 学做菜
    Java实现 蓝桥杯VIP 算法训练 判断字符位置
    Java实现 蓝桥杯VIP 算法训练 判断字符位置
    Java实现 蓝桥杯VIP 算法训练 链表数据求和操作
  • 原文地址:https://www.cnblogs.com/zhanggaofeng/p/6264047.html
Copyright © 2011-2022 走看看