zoukankan      html  css  js  c++  java
  • MYSQL——表相关操作(多表查询【联表查询&子查询】)

    一、多表查询——多表联合查询

    
    
    # 方案1:链表查询
    把多张物理表合并成一张虚拟表,再进行后续查询
    
    #======>内链接:保留两张表有对应关系的记录
    select * from emp,dep where emp.dep_id=dep.id;
    select dep.name,emp.name from emp inner join dep on emp.dep_id=dep.id
        where dep.name = "技术";
    
    #======>左链接:在内链接的基础上保留左表的记录
    select * from emp left join dep on emp.dep_id=dep.id;
    
    #======>右链接:在内链接的基础上保留右表的记录
    select * from emp right join dep on emp.dep_id=dep.id;
    
    #======>全外链接:在内链接的基础上保留左右表的记录
    full join
    
    select * from emp left join dep on emp.dep_id=dep.id
    union
    select * from emp right join dep on emp.dep_id=dep.id;
    
    
    示例1:查询所有部门名及对应的员工个数
    select dep.name,count(emp.id) from emp right join dep on emp.dep_id = dep.id
    group by dep.name
    ;
    
    select dep.name,count(emp.id) from emp right join dep on emp.dep_id = dep.id
    group by dep.name
    having count(emp.id) < 2
    ;
    
    #示例2:即找出年龄大于25岁的员工以及员工所在的部门
    select emp.name,dep.name from emp inner join dep on emp.dep_id = dep.id where age > 25;
    
    
    #示例3:以内连接的方式查询employee和department表,并且以age字段的升序方式显示
    
    
    # 把多张表链接到一起:
    select * from
    (select emp.*,dep.name as dep_name  from emp inner join dep on emp.dep_id = dep.id) as t1
    inner join
    dep
    on t1.dep_id = dep.id
    ;
    
    select * from emp
    inner join dep
    on emp.dep_id = dep.id
    
    inner join dep as t1
    on t1.id = dep.id;
    
    
    # 查询部门内最新入职的员工
    select * from employee
    inner join
    (select depart_id,max(hire_date) as maxd from employee group by depart_id) as t1
    on employee.depart_id = t1.depart_id
    where employee.hire_date = t1.maxd
    ;
    
    
    

    二、多表查询——子查询

    # 方案2:子查询
    从一张表中查询出结果,用该结果作为查
    询下一张表的过滤条件
    select * from employee
    where hire_date =  (select max(hire_date) from employee);
    
    
    #查询平均年龄在25岁以上的部门名
    select * from dep where id in
    (select dep_id from emp group by dep_id having avg(age) > 25);
    
    #查看技术部员工姓名
    select * from emp where dep_id in
    (select id from dep where name="技术");
    
    #查看不足1人的部门名(子查询得到的是有人的部门id)
    select * from dep where id not in (select distinct dep_id from emp);
    
    select * from dep where exists (select * from emp where id>3);

    三、详细介绍子查询

    1:子查询是将一个查询语句嵌套在另一个查询语句中。
    2:内层查询语句的查询结果,可以为外层查询语句提供查询条件。
    3:子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等关键字
    4:还可以包含比较运算符:= 、 !=、> 、<等

    1、in关键字的子查询
    # 1、in
    select * from emp where age=18 or age=38 or age=28;
    select * from emp where age in (18,38,28);
    
    # 子查询的思路
    select * from emp where dep_id in
    (select id from dep where name="技术" or name="销售");
    
    # 链表的思路
    select * from emp inner join dep
    on emp.dep_id = dep.id
    where dep.name in ("技术","销售");
    
    
    # not in不支持null
    mysql> select * from dep;
    +------+--------------+
    | id   | name         |
    +------+--------------+
    |  200 | 技术         |
    |  201 | 人力资源     |
    |  202 | 销售         |
    |  203 | 运营         |
    +------+--------------+
    4 rows in set (0.00 sec)
    mysql> insert into emp values(7,'lili','female',48,null);
    Query OK, 1 row affected (0.03 sec)
    
    mysql> select * from emp
        -> ;
    +----+------------+--------+------+--------+
    | id | name       | sex    | age  | dep_id |
    +----+------------+--------+------+--------+
    |  1 | egon       | male   |   18 |    200 |
    |  2 | alex       | female |   48 |    201 |
    |  3 | wupeiqi    | male   |   38 |    201 |
    |  4 | yuanhao    | female |   28 |    202 |
    |  5 | liwenzhou  | male   |   18 |    200 |
    |  6 | jingliyang | female |   18 |    204 |
    |  7 | lili       | female |   48 |   NULL |
    +----+------------+--------+------+--------+
    7 rows in set (0.00 sec)
    
    mysql>
    
    
    查询出有员工的部门,
    select * from dep where id in
    (select distinct dep_id from emp);
    
    查询出没有员工的部门,
    select * from dep where id not in
    (select distinct dep_id from emp);
    
    
    select * from dep where id not in
    (select distinct dep_id from emp where dep_id is not null);

    2、any 和 all关键字的子查询

    # any后也跟子查询语句,与in不一样的地方在哪里
    #   in (子查询语句)
    #   in (值1,值2,值3)
    #   而any只能跟子查询语句
    #   any必须跟比较运算符配合使用
    
    select * from emp where dep_id in
    (select id from dep where name in ("技术","人力资源"));
    
    select * from emp where dep_id = any
    (select id from dep where name in ("技术","人力资源"));
    
    
    select * from emp where dep_id not in
    (select id from dep where name in ("技术","人力资源"));
    
    select * from emp where ! (dep_id = any(select id from dep where name in ("技术","人力资源")));
    
    
    查询出那些薪资比所有部门的平均薪资都高的员工=》薪资在所有部门平均线以上的狗币资本家
    select * from employee where salary > all
    (select avg(salary) from employee where depart_id is not null group by depart_id);
    
    查询出那些薪资比所有部门的平均薪资都低的员工=》薪资在所有部门平均线以下的无产阶级劳苦大众
    select * from employee where salary < all
    (select avg(salary) from employee where depart_id is not null group by depart_id);
    
    查询出那些薪资比任意一个部门的平均薪资高的员工=》薪资在任一部门平均线以上的员工
    select * from employee where salary > any
    (select avg(salary) from employee where depart_id is not null group by depart_id);
    
    
    select * from employee where salary < any
    (select avg(salary) from employee where depart_id is not null group by depart_id);

    3、exists关键字的子查询

    ps:

     exists (子查询语句,不能用集合体)
    not exists底层用索引,以提升效率
    not in即便是有索引也没有用,因为他要把所有的值都走一遍

    not exists 效率高于not in,因为底层用索引原因 

    # exists  对比 in
    # in的效率 高于 exists
    in 先把子查询语句查出结果集再应用到外层里
    exists在外层取一条记录,内层子查询语句都要执行一遍,所以叫相关子查询
    select * from 表1 where exists (select * from 表2); # 例如:查询有员工的部门=》 select * from dep where exists (select * from emp where dep.id=emp.dep_id); # not exists的效果 高于 not in select * from dep where not exists (select * from emp where 203=emp.dep_id); # 例:查询选修了所有课程的学生id、name: # 实现方式一:选修了三门课程的学生就是选修了所有课程的学生 select s.id,s.name from student as s inner join student2course as sc on s.id = sc.sid group by sc.sid having count(sc.cid) = (select count(id) from course); # 实现方式二:找到这样的学生,该学生不存在没有选修过的课程 select * from student as s where not exists ( select * from course as c not exists ( select * from student2course as sc where sc.sid = s.id and sc.cid = c.id ) ); select * from student as s where not exists ( select * from course as c where not exists ( select * from student2course as sc where sc.sid = s.id and sc.cid = c.id ) ); 学生记录可以过滤出来,一定是子查询内没有记录 for 学生: # s.id=2 for 课程: # c.id=1 for 学生2课程: # sc.sid = 2 and sc.cid = 1 pass ================================== for sid in [1,2,3,4]: for cid in [1,2,3]: (sid,cid) 最外层循环一次 # (1,1) # (1,2) # (1,3) 最外层循环二次 # (2,1) # (2,2) # (2,3) 最外层循环三次 # (3,1) # (3,2) # (3,3) 最外层循环四次 # (4,1) # (4,2) # (4,3) =================================== # 例2、查询没有选择所有课程的学生,即没有全选的学生。=》找出这样的学生,存在没有选修过的课程 select * from student as s where exists ( select * from course as c where not exists ( select * from student2course as sc where sc.sid = s.id and sc.cid = c.id ) ); # 例3、查询一门课也没有选的学生=》找出这样的学生,不存在选修过的课程 select * from student as s where not exists ( select * from course as c where exists ( select * from student2course as sc where sc.sid = s.id and sc.cid = c.id ) ); # 例4、查询至少选修了一门课程的学生=》找出这样的学生,存在选修过课程 select * from student as s where exists ( select * from course as c where exists ( select * from student2course as sc where sc.sid = s.id and sc.cid = c.id ) );

    4、in与exists的区别

    !!!!!!当in和exists在查询效率上比较时,in查询的效率快于exists的查询效率!!!!!!
    
    ==============================exists==============================
    # exists
    exists后面一般都是子查询,后面的子查询被称做相关子查询(即与主语句相关),当子查询返回行数时,exists条件返回true,
    否则返回false,exists是不返回列表的值的,exists只在乎括号里的数据能不能查找出来,是否存在这样的记录。
    
    #
    查询出那些班级里有学生的班级
    select * from class where exists (select * from stu where stu.cid=class.id)
    
    # exists的执行原理为:
    1、依次执行外部查询:即select * from class 
    2、然后为外部查询返回的每一行分别执行一次子查询:即(select * from stu where stu.cid=class.cid)
    3、子查询如果返回行,则exists条件成立,条件成立则输出外部查询取出的那条记录
    
    ==============================in==============================
    # in
    in后跟的都是子查询,in()后面的子查询 是返回结果集的
    
    #
    查询和所有女生年龄相同的男生
    select * from stu where sex='' and age in(select age from stu where sex='')
    
    # in的执行原理为:
    in()的执行次序和exists()不一样,in()的子查询会先产生结果集,
    然后主查询再去结果集里去找符合要求的字段列表去.符合要求的输出,反之则不输出.

    5、带比较运算符的子查询

    #比较运算符:=、!=、>、>=、<、<=、<>
    #查询大于所有人平均年龄的员工名与年龄
    mysql> select name,age from emp where age > (select avg(age) from emp);
    +---------+------+
    | name | age |
    +---------+------+
    | alex | 48 |
    | wupeiqi | 38 |
    +---------+------+
    2 rows in set (0.00 sec)
    
    
    #查询大于部门内平均年龄的员工名、年龄
    select t1.name,t1.age from emp t1
    inner join 
    (select dep_id,avg(age) avg_age from emp group by dep_id) t2
    on t1.dep_id = t2.dep_id
    where t1.age > t2.avg_age; 

    四、

     ---45---

  • 相关阅读:
    第九周作业
    第八周
    第七周
    Jmeter连接到Mysql
    数据库常用链接URL写法
    功能测试方法
    常建输入框的测试
    系统业务流程测试(转)
    Linux
    搭建Git服务器
  • 原文地址:https://www.cnblogs.com/guojieying/p/13629265.html
Copyright © 2011-2022 走看看