zoukankan      html  css  js  c++  java
  • 数据库操作核心-DQL查询语句

    多表查询

      多表查询,又称表联合查询,即一条sql语句涉及到的表有多张,数据通过特定的连接进行联合显示.

    笛卡尔积
      在数学中,两个集合X和Y的笛卡尓积(Cartesian product),又称直积,表示为X × Y.
      假设集合A={a, b},集合B={0, 1, 2},则两个集合的笛卡尔积为{(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}。
      在数据库中,如果直接查询俩张表,那么其查询结果就会产生笛卡尔积
    例如:
      select *
      from s_emp,s_dept;

    连接查询
      为了在多表查询中避免笛卡尔积的产生,我们可以使用连接查询来解决这个问题.
      连接查询分为:
        1.等值连接
        2.不等值连接
        3.外连接
          左外连接
          右外连接
          全外连接
        4.自连接

    1.等值连接
    利用一张表中某列的值和另一张表中某列的值相等的关系,把俩张表连接起来。
    例如:查询员工的名字、部门编号、部门名字

    select last_name,dept_id,name
    from s_emp,s_dept
    where s_emp.dept_id=s_dept.id;

    为了表述的更加清楚,可以给每张表起别名

    select se.last_name,se.dept_id,sd.id,sd.name 
    from s_emp se,s_dept sd
    where se.dept_id=sd.id;

    2.不等值连接
    假设数据库中还有一张工资等级表:salgrade
      工资等级表salgrade:
      gradeName列表示等级名称
      losal 列表示这个级别的最低工资数
      hisal 列表示这个级别的最高工资数

    表中的数据类似于下面内容:
      id  salgrade  losal  hisal
      1  初级程序员 2000  4000
      2  中级程序员 4000  6000

    create table salgrade(
    id         number primary key,
    gradeName  varchar2(200) not null,
    losal     number,
    hisal        number
    );        

    例如:
    查询出员工的名字、职位、工资、工资等级名称

    SELECT e.last_name, e.title, e.salary, s.gradeName
    FROM s_emp e, salgrade s
    WHERE e.salary BETWEEN s.losal AND s.hisal

    3.外连接

    外连接分为:  左外连接  右外连接  全连接

    先分别在俩s_emp和s_dept表中插入新的数据
    特点:新员工tom不在任何部门,新增部门st下面没有任何员工
      insert into s_emp(id,last_name) values(26,'tom');
      insert into s_dept(id,name) values(60,'st');
      commit;

    下面条sql语句可以把上面插入的数据给删除掉
      delete from s_emp where id=26;
      delete from s_dept where id=60;
      commit;

    这个时候再使用等值连接的话,查询出来的数据就会少,因为新增的员工tom和部门表中的数据连接不上,
    当然新增的部门st也和员工表中的数据连接不上.那么这俩条数据都是在等值连接中查询不出来.

      左外连接
      例如:
      查询所有员工 以及对应的部门的名字,没有部门的员工也要显示出来

      select last_name,dept_id,name 
      from s_emp,s_dept
      where s_emp.dept_id=s_dept.id(+);

      或者 俩者是等价的

      select last_name,dept_id,name 
      from s_emp left outer join s_dept
      on s_emp.dept_id=s_dept.id;

      注意:outer可以省去不写

      右外连接
      例如:
      查询所有员工 以及对应的部门的名字,没有任何员工的部门也要显示出来

      select last_name,dept_id,name 
      from s_emp,s_dept
      where s_emp.dept_id(+)=s_dept.id;
    
      select last_name,dept_id,name 
      from s_emp right outer join s_dept
      on s_emp.dept_id=s_dept.id;

      注意:outer可以省去不写

      注:左右连接的操作要找好基准表。

      全连接
      例如:
      查询所有员工 以及对应的部门的名字,没有任何员工的部门也要显示出来,没有部门的员工也要显示出来

      select last_name,dept_id,name 
      from s_emp full outer join s_dept 
      on s_emp.dept_id=s_dept.id;

      注意:outer可以省去不写

      自连接
      一张表,自己和自己连接
      例如:
      查询每个员工的名字以及员工对应的管理者的名字

      select s1.last_name,s2.last_name manager_name
      from s_emp s1,s_emp s2
      where s1.manager_id = s2.id;

    4.对查询结果集的操作

    如果有俩条sql语句,每一条sql都可以查询出一个结果,这个被称之为结果集。那么我们可以使用下面的关键字对俩个结果集进行操作
    union 取俩个结果集的并集
    union all 把俩个结果集合在一起显示出来
    minus 第一个结果集除去第二个结果集和它相同的部分
    intersect 求俩个结果集的交集

    注意:前提条件 俩个结果集中查询的列要完全一致

      union 取俩个结果集的并集
    例如:

    select last_name,dept_id,name from s_emp,s_dept where s_emp.dept_id=s_dept.id(+)
    union
    select last_name,dept_id,name from s_emp,s_dept where s_emp.dept_id(+)=s_dept.id;

      union all 把俩个结果集合在一起显示出来
    例如:

    select last_name,dept_id,name from s_emp,s_dept where s_emp.dept_id=s_dept.id(+)
    union all
    select last_name,dept_id,name from s_emp,s_dept where s_emp.dept_id(+)=s_dept.id;

      minus 第一个结果集除去第二个结果集和它相同的部分
    例如:

    select last_name,dept_id,name from s_emp,s_dept where s_emp.dept_id=s_dept.id(+)
    minus
    select last_name,dept_id,name from s_emp,s_dept where s_emp.dept_id(+)=s_dept.id;

      intersect 求俩个结果集的交集

    select last_name,dept_id,name from s_emp,s_dept where s_emp.dept_id=s_dept.id(+)
    intersect
    select last_name,dept_id,name from s_emp,s_dept where s_emp.dept_id(+)=s_dept.id;

    组函数

    group by 在查询表中数据的时候进行分组的关键字
    思考:为什么要对数据进行分组
    having 分组之后的进行进一步数据筛选的关键字
    having和where的功能类似

    组函数(分组函数),是指将数据按照某列的值进行分组后,然后使用组函数分别对每个分好的小组中的数据进行处理。所以组函数一般要结合着分组关键字group来使用

    组函数:
      avg 求平均值
      count 计算有多少条数据
      max 最大值
      min 最小值
      sum 求和

      stddev 标准差
      variance 方差

    sql语句的各部分构成
      select ....
      from ....
      where ....
      group by ...
      having ...
      order by ....

    注:除了select和from之外其他的都不是必须的。

    假如select..from..后面的语句都出现了,那么他们的执行顺序为:
      where-->group by分组-->执行组函数-->having筛选->order by

    组函数出现的位置:
      1.select后面
      2.having后面
      3.order by后面
      4.where后面一定【不能】出现组函数

    !!!注意:如果select/having语句后面出现了组函数,那么select/having后面没有被组函数修饰的列,就必须出现在group by 后面

    where和having对比:
      1.where和having都是做条件筛选的
      2.where执行的时间比having要早
      3.where后面不能出现组函数
      4.having后面可以出现组函数
      5.where语句要紧跟from后面
      6.having语句要紧跟group by后面

    group by和having的关系:
      1.group by可以单独存在,后面可以不出现having语句
      2.having不能单独存在,有需要的话,必须出现在group by后面

    order by语句
      1.如果sql语句中需要排序,那么就一定要写在sql语句的最后面
      2.order by后也可以出现组函数

    使用组函数:不结合group分组使用
      如果不使用group分组的话,那么默认当前查询到的所有数据是一组

    使用组函数:结合group分组以及having筛选使用
      例如:
        查询s_emp表中部门的平均工资大于等于1400的部门

        select dept_id,avg(salary)
        from s_emp
        group by dept_id
        having avg(salary)>=1400;

    思考:上面的sql语句修改为如下,是否可以?where后不可以使用组函数 group function is not allowed here

    组函数练习:
    查询s_emp表每个部门的最大工资数,并且显示出这个最大工资的员工名字以及该部门的名字和该部门所属区域,并且使用部门编号进行排序
    select max(s1.salary),s1.dept_id,s_dept.name,s2.last_name,s_region.name as regionname
    from s_emp s1,s_emp s2,s_dept,s_region
    where 
        s1.dept_id=s_dept.id
        and
        s_dept.region_id=s_region.id
    group by s1.dept_id,s2.salary,s2.last_name,s_dept.name,s_region.name
    having s2.salary=max(s1.salary)
    order by s1.dept_id;
    注:如果只是针对一个表进行操作,那么分组时的 group by 后的所有字段,都会对分组结果产生影响,进而影响到分组函数的使用,所以如下写是不对的:
    select max(s1.salary),dept_id,last_name
    from s_emp s1
    group by dept_id,last_name;
    order by s1.dept_id;
    在这里max(s1.salary),是完全执行完分组后才执行的
    但是如果针对两个表进行操作,那么分组时的 group by 后的字段,分组函数是根据有与其字段有关的那个表进行计算,也就是说如上例:max(s1.salary)
    先是执行了 group by 后的第一个字段 s1.dept_id,而后计算了max(s1.salary),后再执行剩下的字段s2.salary,s2.last_name,s_dept.name,s_region.name
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·
    嵌套查询:
    查询工资比Ngao所在部门平均工资要高的员工信息,同时这个员工所在部门的平均工资也要比Ngao所在部门的平均工资要高显示当前部门的平均工资
    select dept_id 
    from s_emp 
    where last_name='Ngao';
    
    select avg(salary) 
    from s_emp
    where dept_id=(
        select dept_id 
        from s_emp 
        where last_name='Ngao'
    );
    
    select last_name,salary,dept_id
    from s_emp
    where salary>(
        select avg(salary) 
        from s_emp
        where dept_id=(
            select dept_id 
            from s_emp 
            where last_name='Ngao'
        )
    );
    
    select t2.last_name,t2.salary,s_emp.dept_id,avg(s_emp.salary)
    from s_emp,(
        select last_name,salary,dept_id
        from s_emp
        where salary>(
        select avg(salary) 
            from s_emp
            where dept_id=(
                select dept_id 
                from s_emp 
                where last_name='Ngao'
            )
        )
    ) t2
    where s_emp.dept_id=t2.dept_id
    group by s_emp.dept_id,t2.last_name,t2.salary
    having s_emp.dept_id in(
        select distinct dept_id
        from s_emp
        where salary>(
            select avg(salary) 
            from s_emp
            where dept_id=(
                select dept_id 
                from s_emp 
                where last_name='Ngao'
            )
        )
    )    
    and 
    avg(s_emp.salary)>(
        select avg(salary) 
        from s_emp
        where dept_id=(
            select dept_id 
            from s_emp 
            where last_name='Ngao'
        )
    );
  • 相关阅读:
    函数间的调用关系
    二分法原理
    图片1
    C函数讲解
    图片2
    图片1
    图片2
    函数间的调用关系
    C函数讲解
    二分法原理
  • 原文地址:https://www.cnblogs.com/Magic-Li/p/12705888.html
Copyright © 2011-2022 走看看