zoukankan      html  css  js  c++  java
  • day--39-MySQL的多表查询

                                        多表查询
    一:表的基本介绍
        可以参考:https://www.cnblogs.com/cdf-opensource-007/p/6517627.html
        建立一个员工表信息表和一个部门表,每个员工都对应在哪个部门。因此这两张表具有一定关系。需要将两个表格进行查询,找到一个
        员工所对应的所属部门。
    
    01:建立一个员工表:employee 和一个部门表departmentemployee表:
      mysql> create table employee(
            -> id int primary key auto_increment,
            -> name varchar(20),
            -> sex enum("male","female") not null default "male",
            -> age int,
            -> dep_id int
            -> );
        Query OK, 0 rows affected (0.18 sec)
    
        department表:
        mysql> create table department(
            -> id int,
            -> name varchar(20)
            -> );
        Query OK, 0 rows affected (0.12 sec)
     02:给两张表加入信息。
    employee表:
    mysql> insert into employee(name,sex,age,dep_id) values
            -> ("egon","male",18,200),
            -> ("alex","female",48,201),
            -> ("wupeiqi","male",38,210),
            -> ("yuanhao","female",28,202),
            -> ("liwenzhou","female",28,202),
            -> ("jingwen","female",18,204);
        Query OK, 6 rows affected (0.05 sec)
        Records: 6  Duplicates: 0  Warnings: 0

     查看employee的结构:

    mysql> desc employee;
        +--------+-----------------------+------+-----+---------+----------------+
        | Field  | Type                  | Null | Key | Default | Extra          |
        +--------+-----------------------+------+-----+---------+----------------+
        | id     | int(11)               | NO   | PRI | NULL    | auto_increment |
        | name   | varchar(20)           | YES  |     | NULL    |                |
        | sex    | enum('male','female') | NO   |     | male    |                |
        | age    | int(11)               | YES  |     | NULL    |                |
        | dep_id | int(11)               | YES  |     | NULL    |                |
        +--------+-----------------------+------+-----+---------+----------------+
        5 rows in set (0.00 sec)
    
    

       查看employee的信息:

    
    
    mysql> select * from employee;
        +----+-----------+--------+------+--------+
        | id | name      | sex    | age  | dep_id |
        +----+-----------+--------+------+--------+
        |  1 | egon      | male   |   18 |    200 |
        |  2 | alex      | female |   48 |    201 |
        |  3 | wupeiqi   | male   |   38 |    210 |
        |  4 | yuanhao   | female |   28 |    202 |
        |  5 | liwenzhou | female |   28 |    202 |
        |  6 | jingwen   | female |   18 |    204 |
        +----+-----------+--------+------+--------+
        6 rows in set (0.00 sec)
    department表:
    mysql> insert into department values
            -> (200,"技术"),
            -> (201,"人力资源"),
            -> (202,"销售"),
            -> (203,"运营");
        Query OK, 4 rows affected (0.04 sec)
        Records: 4  Duplicates: 0  Warnings: 0
    
        department的结构:
        mysql> desc department;
        +-------+-------------+------+-----+---------+-------+
        | Field | Type        | Null | Key | Default | Extra |
        +-------+-------------+------+-----+---------+-------+
        | id    | int(11)     | YES  |     | NULL    |       |
        | name  | varchar(20) | YES  |     | NULL    |       |
        +-------+-------------+------+-----+---------+-------+
        2 rows in set (0.00 sec)
     department的信息:
    mysql> select * from department;
        +------+--------------+
        | id   | name         |
        +------+--------------+
        |  200 | 技术         |
        |  201 | 人力资源     |
        |  202 | 销售         |
        |  203 | 运营         |
        +------+--------------+
        4 rows in set (0.00 sec)
    
    

    二:多表查询(以employee和department为例)

    #重点:外链接语法:   select 字段列表 from 表1 inner/left/right join 表2  on  表1.字段=表2.字段;
    01:交叉链接:生成笛卡儿积:
      
    mysql> select * from employee,department;
        +----+-----------+--------+------+--------+------+--------------+
        | id | name      | sex    | age  | dep_id | id   | name         |
        +----+-----------+--------+------+--------+------+--------------+
        |  1 | egon      | male   |   18 |    200 |  200 | 技术         |
        |  1 | egon      | male   |   18 |    200 |  201 | 人力资源     |
        |  1 | egon      | male   |   18 |    200 |  202 | 销售         |
        |  1 | egon      | male   |   18 |    200 |  203 | 运营         |
        |  2 | alex      | female |   48 |    201 |  200 | 技术         |
        |  2 | alex      | female |   48 |    201 |  201 | 人力资源     |
        |  2 | alex      | female |   48 |    201 |  202 | 销售         |
        |  2 | alex      | female |   48 |    201 |  203 | 运营         |
        |  3 | wupeiqi   | male   |   38 |    210 |  200 | 技术         |
        |  3 | wupeiqi   | male   |   38 |    210 |  201 | 人力资源     |
        |  3 | wupeiqi   | male   |   38 |    210 |  202 | 销售         |
        |  3 | wupeiqi   | male   |   38 |    210 |  203 | 运营         |
        |  4 | yuanhao   | female |   28 |    202 |  200 | 技术         |
        |  4 | yuanhao   | female |   28 |    202 |  201 | 人力资源     |
        |  4 | yuanhao   | female |   28 |    202 |  202 | 销售         |
        |  4 | yuanhao   | female |   28 |    202 |  203 | 运营         |
        |  5 | liwenzhou | female |   28 |    202 |  200 | 技术         |
        |  5 | liwenzhou | female |   28 |    202 |  201 | 人力资源     |
        |  5 | liwenzhou | female |   28 |    202 |  202 | 销售         |
        |  5 | liwenzhou | female |   28 |    202 |  203 | 运营         |
        |  6 | jingwen   | female |   18 |    204 |  200 | 技术         |
        |  6 | jingwen   | female |   18 |    204 |  201 | 人力资源     |
        |  6 | jingwen   | female |   18 |    204 |  202 | 销售         |
        |  6 | jingwen   | female |   18 |    204 |  203 | 运营         |
        +----+-----------+--------+------+--------+------+--------------+
        24 rows in set (0.00 sec)
        这种显示是将所有列表排序都生成了,我们要找的排序肯定会在这个笛卡儿积表格中,但是不利于分析。
    View Code
    02:内链接,只链接匹配的行。
      
    mysql> select * from employee,department where department.id=employee.dep_id;  #where条件分析。
        +----+-----------+--------+------+--------+------+--------------+
        | id | name      | sex    | age  | dep_id | id   | name         |
        +----+-----------+--------+------+--------+------+--------------+
        |  1 | egon      | male   |   18 |    200 |  200 | 技术         |
        |  2 | alex      | female |   48 |    201 |  201 | 人力资源     |
        |  4 | yuanhao   | female |   28 |    202 |  202 | 销售         |
        |  5 | liwenzhou | female |   28 |    202 |  202 | 销售         |
        +----+-----------+--------+------+--------+------+--------------+
        4 rows in set (0.00 sec)
    View Code
    #再看一个需求,我要查出技术部的员工的名字
      mysql> select name from employee,department where employee.dep_id=department.id and department.name='技术';
        ERROR 1052 (23000): Column 'name' in field list is ambiguous
        #上面直接就报错了,因为select后面直接写的name,在两个表合并起来的表中,是有两个name字段的,直接写name是不行的,要加上表名,再看:
        mysql> select employee.name from employee,department where employee.dep_id=department.id and department.name="技术";
        +------+
        | name |
        +------+
        | egon |
        +------+
        1 row in set (0.00 sec)

      03:外链接之左链接:优先显示左边表的全部记录

      #以左表为准,即找出所有员工信息,当然包括没有部门的员工
        #本质就是:在内链接的基础上增加左边有而右边没有的结果
            mysql> select employee.id,employee.name,department.name as depart_name from employee
                 > left join department on employee.dep_id=department.id;
                +----+-----------+--------------+
                | id | name      | depart_name  |
                +----+-----------+--------------+
                |  1 | egon      | 技术         |
                |  2 | alex      | 人力资源     |
                |  4 | yuanhao   | 销售         |
                |  5 | liwenzhou | 销售         |
                |  3 | wupeiqi   | NULL         |
                |  6 | jingwen   | NULL         |
                +----+-----------+--------------+
                6 rows in set (0.00 sec)
    04:外链接之右链接:优先显示右边表的全部记录
      #以右表为准,即找出所有员工信息,当然包括没有部门的员工
        #本质就是:在内链接的基础上增加右边有而左边没有的结果
        mysql> select employee.id,employee.name,department.name as depart_name from
        -> employee right join department on
        -> employee.dep_id=department.id;
        +------+-----------+--------------+
        | id   | name      | depart_name  |
        +------+-----------+--------------+
        |    1 | egon      | 技术         |
        |    2 | alex      | 人力资源     |
        |    4 | yuanhao   | 销售         |
        |    5 | liwenzhou | 销售         |
        | NULL | NULL      | 运营         |
        +------+-----------+--------------+
        5 rows in set (0.00 sec)
    05:全外链接:显示左右两个表的全部内容
    001:union显示的左右两边的数据,并将重复的数据去重。
          
    mysql> select * from employee left join department on employee.dep_id=department.id
            -> union
            -> select * from employee right join department on employee.dep_id=department.id
            -> ;
        +------+-----------+--------+------+--------+------+--------------+
        | id   | name      | sex    | age  | dep_id | id   | name         |
        +------+-----------+--------+------+--------+------+--------------+
        |    1 | egon      | male   |   18 |    200 |  200 | 技术         |
        |    2 | alex      | female |   48 |    201 |  201 | 人力资源     |
        |    4 | yuanhao   | female |   28 |    202 |  202 | 销售         |
        |    5 | liwenzhou | female |   28 |    202 |  202 | 销售         |
        |    3 | wupeiqi   | male   |   38 |    210 | NULL | NULL         |
        |    6 | jingwen   | female |   18 |    204 | NULL | NULL         |
        | NULL | NULL      | NULL   | NULL |   NULL |  203 | 运营         |
        +------+-----------+--------+------+--------+------+--------------+
        7 rows in set (0.06 sec)
    View Code
        002:union all  显示的是左右两边表的数据,并不会去重
        
    mysql> select * from employee left join department on employee.dep_id=department.id
            -> union all
            -> select * from employee right join department on employee.dep_id=department.id;
        +------+-----------+--------+------+--------+------+--------------+
        | id   | name      | sex    | age  | dep_id | id   | name         |
        +------+-----------+--------+------+--------+------+--------------+
        |    1 | egon      | male   |   18 |    200 |  200 | 技术         |
        |    2 | alex      | female |   48 |    201 |  201 | 人力资源     |
        |    4 | yuanhao   | female |   28 |    202 |  202 | 销售         |
        |    5 | liwenzhou | female |   28 |    202 |  202 | 销售         |
        |    3 | wupeiqi   | male   |   38 |    210 | NULL | NULL         |
        |    6 | jingwen   | female |   18 |    204 | NULL | NULL         |
        |    1 | egon      | male   |   18 |    200 |  200 | 技术         |
        |    2 | alex      | female |   48 |    201 |  201 | 人力资源     |
        |    4 | yuanhao   | female |   28 |    202 |  202 | 销售         |
        |    5 | liwenzhou | female |   28 |    202 |  202 | 销售         |
        | NULL | NULL      | NULL   | NULL |   NULL |  203 | 运营         |
        +------+-----------+--------+------+--------+------+--------------+
        11 rows in set (0.00 sec)
    View Code
    三:符合条件接连的查询
    1、
    #示例1:以内连接的方式查询employee和department表,并且employee表中的age字段值必须大于25,即找出年龄大于25岁的员工以及员工所在的部门
        mysql> select employee.name,department.name from employee inner join department
            -> on employee.dep_id=department.id
            -> where age>25;
        +-----------+--------------+
        | name      | name         |
        +-----------+--------------+
        | alex      | 人力资源     |
        | yuanhao   | 销售         |
        | liwenzhou | 销售         |
        +-----------+--------------+
        3 rows in set (0.00 sec)
    2、#实例:以内连接的方式查询employee和department表,并且以age字段的生序方式显示;
      
    实例01:内连接的方式查询employee和department表,并且employee表中的age字段值必须大于25,即找出年龄大于25岁的员工以及员工所在的部门
            mysql> select employee.name,department.name from employee inner join department
                -> on employee.dep_id=department.id  where age>25
                -> order by age;    #(order by  排序是默认的升序的,升序order by asc)
            +-----------+--------------+
            | name      | name         |
            +-----------+--------------+
            | yuanhao   | 销售         |
            | liwenzhou | 销售         |
            | alex      | 人力资源     |
            +-----------+--------------+
            3 rows in set (0.00 sec)
    实例一
      
    实例02:以内连接的方式查询employee和department表,并且以age字段的升序方式显示
            mysql> select employee.id,employee.name,employee.age,department.name from employee,department
                -> where employee.dep_id=department.id
                -> and age >25
                -> order by age asc;
            +----+-----------+------+--------------+
            | id | name      | age  | name         |
            +----+-----------+------+--------------+
            |  5 | liwenzhou |   28 | 销售         |
            |  4 | yuanhao   |   28 | 销售         |
            |  2 | alex      |   48 | 人力资源     |
            +----+-----------+------+--------------+
            3 rows in set (0.00 sec)
    实例二
    四:子查询
    解释:子查询就是将一个查询结果用括号括起来,交给另外一个sql语句,作为它的一个查询语句来进行操作。
            子查询:
            #1:子查询是将一个查询语句嵌套在另一个查询语句中。
            #2:内层查询语句的查询结果,可以为外层查询语句提供查询条件。
            #3:子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等关键字
            #4:还可以包含比较运算符:= 、 !=、> 、<等
      1: 带in关键字的的字查询:
     mysql> select id,name from department where id in (select dep_id from employee group by
                -> dep_id having avg(age)>25);
            +------+--------------+
            | id   | name         |
            +------+--------------+
            |  201 | 人力资源     |
            |  202 | 销售         |
            +------+--------------+
            2 rows in set (0.05 sec)
    
    
        总结:子查询的思路和解决问题一样,先解决一个然后拿着这个的结果再去解决另外一个问题,连表的思路是先将两个表关联在一起,
        然后在进行group by啊过滤啊等等操作,两者的思路是不一样的.
      
    01:#查询员工平均年龄在25岁以上的部门名,可以用连表,也可以用子查询,
            mysql> select department.name from department inner join employee on department.id=employee.dep_id
                -> group by department.name having avg(age)>25;
            +--------------+
            | name         |
            +--------------+
            | 人力资源     |
            | 销售         |
            +--------------+
    案例01
      
    02:#查看技术部员工姓名
            mysql> select name from employee where dep_id in (select id from department where name="技术");
            +------+
            | name |
            +------+
            | egon |
            +------+
            1 row in set (0.00 sec)
    案例02
      
    03:#查看不足1人的部门名(子查询得到的是有人的部门id)
            mysql> select id,name from department where id not in (select distinct dep_id from employee);
            +------+--------+
            | id   | name   |
            +------+--------+
            |  203 | 运营   |
            +------+--------+
            1 row in set (0.00 sec)
    案例03
    2:比较运算符的子查询:
    #比较运算符:=、!=、>、>=、<、<=、<>
        #查询大于所有人平均年龄的员工名与年龄
        mysql> select name,age from employee where age >(select avg(age) from employee);
        +---------+------+
        | name    | age  |
        +---------+------+
        | alex    |   48 |
        | wupeiqi |   38 |
        +---------+------+
        2 rows in set (0.00 sec)
      3:带exists(存在)关键字的子查询
      EXISTS关字键字表示存在。在使用EXISTS关键字时,内层查询语句不返回查询的记录。而是返回一个真假值。True或False
      当返回True时,外层查询语句将进行查询;当返回值为False时,外层查询语句不进行查询。还可以写not exists,和exists的效果就是反的
        01:employee表中不存在id为200    
       mysql> select * from employee where exists (select id from employee where id=500);
        Empty set (0.00 sec) 
        02:employee存在的情况:
      #只有当括号里面的条件成立了,select * from employee  才会执行
        mysql> select * from employee where exists (select dep_id from employee where dep_id=200);
        +----+-----------+--------+------+--------+
        | id | name      | sex    | age  | dep_id |
        +----+-----------+--------+------+--------+
        |  1 | egon      | male   |   18 |    200 |
        |  2 | alex      | female |   48 |    201 |
        |  3 | wupeiqi   | male   |   38 |    210 |
        |  4 | yuanhao   | female |   28 |    202 |
        |  5 | liwenzhou | female |   28 |    202 |
        |  6 | jingwen   | female |   18 |    204 |
        +----+-----------+--------+------+--------+
        6 rows in set (0.00 sec)
    
    
    





  • 相关阅读:
    CF960G-Bandit Blues【第一类斯特林数,分治,NTT】
    P6122-[NEERC2016]Mole Tunnels【模拟费用流】
    P5404-[CTS2019]重复【KMP,dp】
    P5405-[CTS2019]氪金手游【树形dp,容斥,数学期望】
    T183637-变异距离(2021 CoE III C)【单调栈】
    61-A
    2021-4-1考试
    JAVA日常练习—程序输入string转化为int并求和
    并发编程
    git clone 报filename too long 错误的解决方法
  • 原文地址:https://www.cnblogs.com/one-tom/p/10146410.html
Copyright © 2011-2022 走看看