一、多表关系

  • 一对多或者多对一

    • 案例:部门与员工的关系
    • 关系:一个部门对应多个员工,一个员工对应一个部门(不考虑跨部门的特殊情况)
    • 实现:在多的一方建立外键,指向一的一方的主键,这里员工表是多的的一方,部门表是一的一方

      

  • 多对多

    • 案例:学生与课程的关系
    • 关系:一个学生可以选修多门课程,一门课程也可以供多个学生选择
    • 实现:建立第三张中间表,中间表至少包含两个外键,分别关联两方主键  

      

  • 一对一

    • 案例:用户与用户详情的关系
    • 关系:一对一关系,多用于单表拆分,将一张表的基础字段放在一张表,其他详情字段放在另外一张表中,艺体生操作效率
    • 实现:在任意一方加入外键,关联另外一方的主键,并且设置为唯一的(unique)
    • 说明:这个是外键user_id需要加一个约束保证其唯一,从而保证一个详情只能对应一个用户。

      

二、多表查询

  2.1、概述:

    多表查询指从多张数据表中查询数据

  2.2、分类:

    • 连接查询

      • 内连接:相当于查询A、B交集部分数据
      • 外连接
        • 左外连接:查询左表所有数据,以及两张表交集部分数据
        • 右外连接:查询右表所有数据,已经两张表交集部分数据:
      • 自连接:当前表与自身的连接查询,连接必须使用表别名
    • 子查询
    • 联合查询

三、示例数据表结构及数据

  3.1、emp:员工表结构及数据

mysql> select * from emp;
+----+--------+------+--------------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+--------+------+--------------+--------+------------+-----------+---------+
| 1 | 张三 | 43 | 董事长 | 48000 | 2017-07-20 | NULL | 5 |
| 2 | 李四 | 38 | 项目经理 | 23900 | 2016-08-20 | 1 | 1 |
| 3 | 问问 | 22 | 开发 | 18000 | 2022-07-20 | 2 | 1 |
| 4 | 芳芳 | 22 | 开发 | 21000 | 2019-08-18 | 2 | 1 |
| 5 | 珊珊 | 22 | 开发 | 15000 | 2021-04-10 | 3 | 1 |
| 6 | 娜娜 | 25 | 财务 | 24000 | 2023-07-16 | 1 | 3 |
| 7 | 咔咔 | 25 | 出纳 | 8000 | 2021-07-10 | 6 | 3 |
| 8 | 静静 | 27 | 人事 | 5000 | 2021-07-11 | 1 | NULL |
+----+--------+------+--------------+--------+------------+-----------+---------+
8 rows in set (0.00 sec)

  3.2、dept:部门表结构及数据

mysql> select * from dept;
+----+-----------+
| id | name |
+----+-----------+
| 1 | 研发部 |
| 2 | 市场部 |
| 3 | 财务部 |
| 4 | 销售部 |
| 5 | 总经办 |
| 6 | 人事部 |
+----+-----------+
6 rows in set (0.00 sec)

  

  3.3、score1:成绩表1结构及数据

mysql> select * from score1;
+----+--------+-------+
| id | name | score |
+----+--------+-------+
| 1 | 张三 | 94 |
| 2 | 李四 | 93 |
| 3 | 王五 | 87 |
| 4 | 赵六 | 71 |
+----+--------+-------+
4 rows in set (0.00 sec)

  

  3.4、score2:成绩表2结构及数据

mysql> select * from score2;
+----+--------+-------+
| id | name | score |
+----+--------+-------+
| 1 | 张三 | 94 |
| 2 | 李四 | 97 |
| 3 | 王五 | 91 |
| 4 | 赵六 | 82 |
+----+--------+-------+
4 rows in set (0.00 sec)

四、内连接

  4.1、概述:

    内连接查询的是两张表的交集的部分

  4.2、内连接查询语法

    4.2.1 隐式内连接

select 字段列表 from 表1,表2 where 条件...;

    4.2.2 显示内连接 inner可以省略不写

select 字段列表 from 表1 [inner] join 表2 on 连接条件...;   

  4.3、案例

    案例1:查询每个员工的姓名,及关联的部门的名称(隐式内连接实现)

mysql> select emp.name,dept.name as dept_name from emp,dept where emp.dept_id = dept.id;
+--------+-----------+
| name | dept_name |
+--------+-----------+
| 张三 | 总经办 |
| 李四 | 研发部 |
| 问问 | 研发部 |
| 芳芳 | 研发部 |
| 珊珊 | 研发部 |
| 娜娜 | 财务部 |
| 咔咔 | 财务部 |
+--------+-----------+
7 rows in set (0.00 sec)

    案例2:查询每个员工的姓名,及关联的部门的名称(显示内连接实现)

mysql> select emp.name,dept.name as dept_name from emp inner join dept on emp.dept_id = dept.id;
+--------+-----------+
| name | dept_name |
+--------+-----------+
| 张三 | 总经办 |
| 李四 | 研发部 |
| 问问 | 研发部 |
| 芳芳 | 研发部 |
| 珊珊 | 研发部 |
| 娜娜 | 财务部 |
| 咔咔 | 财务部 |
+--------+-----------+
7 rows in set (0.00 sec)

五、外连接

  5.1、左外连接

    简介:相当于查询表1(左表)的所有数据,包含表1和表2交集部分的数据

select 字段列表 from 表1 left [outer] join 表2 on 条件...;

  5.2、右外连接

    简介:相当于查表2(右表)的所有数据,包含表1和表2交集部分的数据

select 字段列表 from 表1 right [outer] join 表2 on 条件...; 

  

  5.3、案例

    案例1:查询emp表的所有数据,和对应的部门信息(左外连接)

mysql> select emp.*, dept.name as dept_name from emp left join dept on emp.dept_id = dept.id;
+----+--------+------+--------------+--------+------------+-----------+---------+-----------+
| id | name | age | job | salary | entrydate | managerid | dept_id | dept_name |
+----+--------+------+--------------+--------+------------+-----------+---------+-----------+
| 1 | 张三 | 43 | 董事长 | 48000 | 2017-07-20 | NULL | 5 | 总经办 |
| 2 | 李四 | 38 | 项目经理 | 23900 | 2016-08-20 | 1 | 1 | 研发部 |
| 3 | 问问 | 22 | 开发 | 18000 | 2022-07-20 | 2 | 1 | 研发部 |
| 4 | 芳芳 | 32 | 开发 | 21000 | 2019-08-18 | 2 | 1 | 研发部 |
| 5 | 珊珊 | 27 | 开发 | 15000 | 2021-04-10 | 3 | 1 | 研发部 |
| 6 | 娜娜 | 25 | 财务 | 24000 | 2023-07-16 | 1 | 3 | 财务部 |
| 7 | 咔咔 | 29 | 出纳 | 8000 | 2021-07-10 | 6 | 3 | 财务部 |
| 8 | 静静 | 27 | 人事 | 5000 | 2021-07-11 | 1 | NULL | NULL |
+----+--------+------+--------------+--------+------------+-----------+---------+-----------+
8 rows in set (0.00 sec)

    说明1:查询emp表的所有数据,即emp.*

    说明2:as dept_name 是给dept.name 起的别名,防止查询结果中出现两个name字段,会有歧义

    说明3:from 后面的是左表,所以该语句中emp是左表

    说明4:join 后面的是右表,所以该语句中的dept是右表

    说明5:连接关系是emp.dept_id = dept.id

    说明6:outer关键字是可以省略的,不影响结果

    案例2:查询dept表的所有数据,和对应的员工信息(右外连接)

mysql> select dept.*, emp.* from emp right join dept on emp.dept_id = dept.id;
+----+-----------+------+--------+------+--------------+--------+------------+-----------+---------+
| id | name | id | name | age | job | salary | entrydate | managerid | dept_id |
+----+-----------+------+--------+------+--------------+--------+------------+-----------+---------+
| 1 | 研发部 | 2 | 李四 | 38 | 项目经理 | 23900 | 2016-08-20 | 1 | 1 |
| 1 | 研发部 | 3 | 问问 | 22 | 开发 | 18000 | 2022-07-20 | 2 | 1 |
| 1 | 研发部 | 4 | 芳芳 | 22 | 开发 | 21000 | 2019-08-18 | 2 | 1 |
| 1 | 研发部 | 5 | 珊珊 | 22 | 开发 | 15000 | 2021-04-10 | 3 | 1 |
| 2 | 市场部 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 3 | 财务部 | 6 | 娜娜 | 25 | 财务 | 24000 | 2023-07-16 | 1 | 3 |
| 3 | 财务部 | 7 | 咔咔 | 25 | 出纳 | 8000 | 2021-07-10 | 6 | 3 |
| 4 | 销售部 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 5 | 总经办 | 1 | 张三 | 43 | 董事长 | 48000 | 2017-07-20 | NULL | 5 |
| 6 | 人事部 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
+----+-----------+------+--------+------+--------------+--------+------------+-----------+---------+
10 rows in set (0.00 sec)

    说明1:查询dept表的所有数据,又因为要求使用右连接,所以需要将右表作为主表,即dept要放在join关键字的后面

    说明2:连接关系依然是emp.dept_id = dept.id

mysql> select dept.*, emp.* from dept left join emp on emp.dept_id = dept.id;
+----+-----------+------+--------+------+--------------+--------+------------+-----------+---------+
| id | name | id | name | age | job | salary | entrydate | managerid | dept_id |
+----+-----------+------+--------+------+--------------+--------+------------+-----------+---------+
| 1 | 研发部 | 2 | 李四 | 38 | 项目经理 | 23900 | 2016-08-20 | 1 | 1 |
| 1 | 研发部 | 3 | 问问 | 22 | 开发 | 18000 | 2022-07-20 | 2 | 1 |
| 1 | 研发部 | 4 | 芳芳 | 22 | 开发 | 21000 | 2019-08-18 | 2 | 1 |
| 1 | 研发部 | 5 | 珊珊 | 22 | 开发 | 15000 | 2021-04-10 | 3 | 1 |
| 2 | 市场部 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 3 | 财务部 | 6 | 娜娜 | 25 | 财务 | 24000 | 2023-07-16 | 1 | 3 |
| 3 | 财务部 | 7 | 咔咔 | 25 | 出纳 | 8000 | 2021-07-10 | 6 | 3 |
| 4 | 销售部 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 5 | 总经办 | 1 | 张三 | 43 | 董事长 | 48000 | 2017-07-20 | NULL | 5 |
| 6 | 人事部 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
+----+-----------+------+--------+------+--------------+--------+------------+-----------+---------+
10 rows in set (0.00 sec)

    说明3:左连接和右连接其实是可以互换的,主要看表的位置

六、自连接

  6.1、自连接查询语法

select 字段列表 from 表A,别名A join 表A 别名B on 条件...;

  6.2、自连接查询

    可以是内连接查询,也可以是外连接查询

  6.3、案例

    案例1:查询员工及其所属的领导的名字

mysql> select a.name, b.name from emp as a,emp as b where a.managerid = b.id;
+--------+--------+
| name | name |
+--------+--------+
| 李四 | 张三 |
| 问问 | 李四 |
| 芳芳 | 李四 |
| 珊珊 | 问问 |
| 娜娜 | 张三 |
| 咔咔 | 娜娜 |
| 静静 | 张三 |
+--------+--------+
7 rows in set (0.00 sec)

    说明1:通过where 将两个表连接起来的方式,内连接方式

    说明2:因为是内连接方式,所以id=1的张三,所属领导为null,就不会被查询出来

    说明3:自连接必须要起别名,而且要给自己起两个别名。相互连接才行,所以自连接,就是一个表起了两个别名互相连接

    案例2:查询所有员工 emp 及其领导的名字,如果员工没有领导也需要查询出来

mysql> select a.name as "员工", b.name as "领导" from emp as a left join emp as b on a.managerid = b.id;
+--------+--------+
| 员工 | 领导 |
+--------+--------+
| 张三 | NULL |
| 李四 | 张三 |
| 问问 | 李四 |
| 芳芳 | 李四 |
| 珊珊 | 问问 |
| 娜娜 | 张三 |
| 咔咔 | 娜娜 |
| 静静 | 张三 |
+--------+--------+
8 rows in set (0.00 sec)

    说明1:因为没有领导的也要查询出来,所以就不能使用内连接,需要使用外连接,left和right都可以

    说明2:同样需要给emp起两个别名

七、联合查询

  7.1、联合查询:

    union / union all 就是把多次查询的结果合并起来,形成一个新的查询结果集

select 字段列表 from 表A ...

union [all]

select 字段列表 from 表B ...

    说明1:union all 会将查询出来的两个结果集全部合并,不会去重

    说明2:union 如果不带all 则会将两个结果集合并,并且去重  

    说明3:对于联合查询的多张表的列数和字段类型必须要保持一致

  

  7.2、案例

    案例1:现在有score1和score2两张成成绩表,将两张表中都大于90分的查找出来合并显示

    分析1:先查询出来score1表中大于90的学生

mysql> select * from score1 where score>90;
+----+--------+-------+
| id | name | score |
+----+--------+-------+
| 1 | 张三 | 94 |
| 2 | 李四 | 93 |
+----+--------+-------+
2 rows in set (0.00 sec)

    分析2:在查询出来score2表中大于90的学生

mysql> select * from score2 where score>90;
+----+--------+-------+
| id | name | score |
+----+--------+-------+
| 1 | 张三 | 94 |
| 2 | 李四 | 97 |
| 3 | 王五 | 91 |
+----+--------+-------+
3 rows in set (0.00 sec)

    分析3:联合查询

mysql> select * from score1 where score>90 union all select * from score2 where score>90;
+----+--------+-------+
| id | name | score |
+----+--------+-------+
| 1 | 张三 | 94 |
| 2 | 李四 | 93 |
| 1 | 张三 | 94 |
| 2 | 李四 | 97 |
| 3 | 王五 | 91 |
+----+--------+-------+
5 rows in set (0.00 sec)

    说明1:因为使用的是union all 所以保留了所有数据

mysql> select * from score1 where score>90 union select * from score2 where score>90;
+----+--------+-------+
| id | name | score |
+----+--------+-------+
| 1 | 张三 | 94 |
| 2 | 李四 | 93 |
| 2 | 李四 | 97 |
| 3 | 王五 | 91 |
+----+--------+-------+
4 rows in set (0.00 sec)

    说明2:去掉了all 直接只使用了union,这个时候张三,94分重复的就只显示一次了

    说明3:李四=93和李四=97,是两个不同的数据,所以不会被合并。

  

八、子查询

  8.1、概念:

    sql语句中嵌套select语句,成为嵌套查询,又称子查询

select * from t1 where column1=(select column1 from t2);

  8.2、根据结果分类

    • 标量子查询:子查询结果为单个值
    • 列子查询:子查询结果为一列
    • 行子查询:子查询结果为一行
    • 表子查询:子查询结果为多行多列

  8.3、根据位置分类

    • where之后的子查询
    • from 之后的子查询
    • select之后的子查询

  8.4、标量子查询

    8.4.1 概念:子查询返回的结果是单个值(数字,字符串,日期等),最简单的形式,这种子查询称为标量子查询

    8.4.2 常用的操作符:=, <, >, >=, <=

    8.4.3 案例

      案例1:查询"研发部"的所有员工信息

        分析1:先查询研发部的部门id

mysql> select id from dept where name="研发部";
+----+
| id |
+----+
| 1 |
+----+
1 row in set (0.00 sec) mysql>

        分析2:根据研发部的部门id,查询员工信息

mysql> select * from emp where dept_id=1;
+----+--------+------+--------------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+--------+------+--------------+--------+------------+-----------+---------+
| 2 | 李四 | 38 | 项目经理 | 23900 | 2016-08-20 | 1 | 1 |
| 3 | 问问 | 22 | 开发 | 18000 | 2022-07-20 | 2 | 1 |
| 4 | 芳芳 | 22 | 开发 | 21000 | 2019-08-18 | 2 | 1 |
| 5 | 珊珊 | 22 | 开发 | 15000 | 2021-04-10 | 3 | 1 |
+----+--------+------+--------------+--------+------------+-----------+---------+
4 rows in set (0.01 sec)

        分析3:使用标量子查询

mysql> select * from emp where dept_id = (select id from dept where name = "研发部");
+----+--------+------+--------------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+--------+------+--------------+--------+------------+-----------+---------+
| 2 | 李四 | 38 | 项目经理 | 23900 | 2016-08-20 | 1 | 1 |
| 3 | 问问 | 22 | 开发 | 18000 | 2022-07-20 | 2 | 1 |
| 4 | 芳芳 | 22 | 开发 | 21000 | 2019-08-18 | 2 | 1 |
| 5 | 珊珊 | 22 | 开发 | 15000 | 2021-04-10 | 3 | 1 |
+----+--------+------+--------------+--------+------------+-----------+---------+
4 rows in set (0.00 sec)

    

      案例2:查询珊珊入职之后的员工信息

        分析1:查询“珊珊”的入职日期

mysql> select entrydate from emp where name = "珊珊";
+------------+
| entrydate |
+------------+
| 2021-04-10 |
+------------+
1 row in set (0.00 sec)

        分析2:查询指定日期之后的入职员工的信息

mysql> select * from emp where entrydate > "2021-04-10";
+----+--------+------+--------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+--------+------+--------+--------+------------+-----------+---------+
| 3 | 问问 | 22 | 开发 | 18000 | 2022-07-20 | 2 | 1 |
| 6 | 娜娜 | 25 | 财务 | 24000 | 2023-07-16 | 1 | 3 |
| 7 | 咔咔 | 25 | 出纳 | 8000 | 2021-07-10 | 6 | 3 |
| 8 | 静静 | 27 | 人事 | 5000 | 2021-07-11 | 1 | NULL |
+----+--------+------+--------+--------+------------+-----------+---------+
4 rows in set (0.00 sec)

        分析3:使用标量查询

mysql> select * from emp where entrydate > (select entrydate from emp where name = "珊珊");
+----+--------+------+--------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+--------+------+--------+--------+------------+-----------+---------+
| 3 | 问问 | 22 | 开发 | 18000 | 2022-07-20 | 2 | 1 |
| 6 | 娜娜 | 25 | 财务 | 24000 | 2023-07-16 | 1 | 3 |
| 7 | 咔咔 | 25 | 出纳 | 8000 | 2021-07-10 | 6 | 3 |
| 8 | 静静 | 27 | 人事 | 5000 | 2021-07-11 | 1 | NULL |
+----+--------+------+--------+--------+------------+-----------+---------+
4 rows in set (0.00 sec)

  8.5、列子查询

    8.5.1 概念:子查询返回的结果是一列(可以是多行),这种子查询称为列子查询

    8.5.2 常用操作符:in, not in, any, some, all

    • in:在指定的集合范围内,多选一
    • not in:不在指定的范围内
    • any:子查询返回列表,有任意一个满足即可
    • some:与any等同,使用some的地方都可以使用any
    • all:子查询返回列表的所有值都必须满足 

    8.5.3 案例

      案例1:查询研发部和财务部的所有员工

        分析1:查询研发部和财务部的部门id

mysql> select id from dept where name="研发部" or name="财务部";
+----+
| id |
+----+
| 1 |
| 3 |
+----+
2 rows in set (0.00 sec)

        分析2:根据部门id,查询员工信息

mysql> select * from emp where dept_id in (1,3);
+----+--------+------+--------------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+--------+------+--------------+--------+------------+-----------+---------+
| 2 | 李四 | 38 | 项目经理 | 23900 | 2016-08-20 | 1 | 1 |
| 3 | 问问 | 22 | 开发 | 18000 | 2022-07-20 | 2 | 1 |
| 4 | 芳芳 | 22 | 开发 | 21000 | 2019-08-18 | 2 | 1 |
| 5 | 珊珊 | 22 | 开发 | 15000 | 2021-04-10 | 3 | 1 |
| 6 | 娜娜 | 25 | 财务 | 24000 | 2023-07-16 | 1 | 3 |
| 7 | 咔咔 | 25 | 出纳 | 8000 | 2021-07-10 | 6 | 3 |
+----+--------+------+--------------+--------+------------+-----------+---------+
6 rows in set (0.00 sec)

        分析3:列子查询结果

mysql> select * from emp where dept_id in (select id from dept where name="研发部" or name="财务部");
+----+--------+------+--------------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+--------+------+--------------+--------+------------+-----------+---------+
| 2 | 李四 | 38 | 项目经理 | 23900 | 2016-08-20 | 1 | 1 |
| 3 | 问问 | 22 | 开发 | 18000 | 2022-07-20 | 2 | 1 |
| 4 | 芳芳 | 22 | 开发 | 21000 | 2019-08-18 | 2 | 1 |
| 5 | 珊珊 | 22 | 开发 | 15000 | 2021-04-10 | 3 | 1 |
| 6 | 娜娜 | 25 | 财务 | 24000 | 2023-07-16 | 1 | 3 |
| 7 | 咔咔 | 25 | 出纳 | 8000 | 2021-07-10 | 6 | 3 |
+----+--------+------+--------------+--------+------------+-----------+---------+
6 rows in set (0.01 sec)

      

      案例2:查询比研发部工资都高的员工

        分析1:查询研发部的部门id

mysql> select id from dept where name="研发部";
+----+
| id |
+----+
| 1 |
+----+
1 row in set (0.00 sec)

        分析2:根据研发部的id,查询出研发部所有人的工资

mysql> select salary from emp where dept_id = (select id from dept where name="研发部");
+--------+
| salary |
+--------+
| 23900 |
| 18000 |
| 21000 |
| 15000 |
+--------+
4 rows in set (0.00 sec)

        分析3:比财务部所有人工资高的员工信息

mysql> select * from emp where salary > all(select salary from emp where dept_id = (select id from dept where name="研发部"));
+----+--------+------+-----------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+--------+------+-----------+--------+------------+-----------+---------+
| 1 | 张三 | 43 | 董事长 | 48000 | 2017-07-20 | NULL | 5 |
| 6 | 娜娜 | 25 | 财务 | 24000 | 2023-07-16 | 1 | 3 |
+----+--------+------+-----------+--------+------------+-----------+---------+
2 rows in set (0.00 sec)

        说明1:比研发部所有人的工资都高,其实就是比研发部最高人的工资还高

      

      案例3:比研发部其中任意一人工资高的员工信息,其实就是比研发部工资最低的人工资高

        分析1:查询研发部所有人的工资

mysql> select salary from emp where dept_id = (select id from dept where name="研发部");
+--------+
| salary |
+--------+
| 23900 |
| 18000 |
| 21000 |
| 15000 |
+--------+
4 rows in set (0.00 sec)

        分析2:比研发部任意一人工资高的员工信息

mysql> select * from emp where salary > any(select salary from emp where dept_id = (select id from dept where name="研发部"));
+----+--------+------+--------------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+--------+------+--------------+--------+------------+-----------+---------+
| 1 | 张三 | 43 | 董事长 | 48000 | 2017-07-20 | NULL | 5 |
| 2 | 李四 | 38 | 项目经理 | 23900 | 2016-08-20 | 1 | 1 |
| 3 | 问问 | 22 | 开发 | 18000 | 2022-07-20 | 2 | 1 |
| 4 | 芳芳 | 22 | 开发 | 21000 | 2019-08-18 | 2 | 1 |
| 6 | 娜娜 | 25 | 财务 | 24000 | 2023-07-16 | 1 | 3 |
+----+--------+------+--------------+--------+------------+-----------+---------+
5 rows in set (0.00 sec)

        说明1:这里的any可以替换成some

  8.6、行子查询

    8.6.1 概念:子查询返回的结果是一行(可以是多列),这种查询称之为行子查询

    8.6.2 常用的操作符:=,!=, in, not in

    8.6.3 案例

      案例1:查询和芳芳在同一个岗位,并且还是同一个直属领带的员工信息

        分析1:先找到芳芳的岗位和直属领导

mysql> select job, managerid from emp where name = "芳芳";
+--------+-----------+
| job | managerid |
+--------+-----------+
| 开发 | 2 |
+--------+-----------+
1 row in set (0.00 sec)

        分析2:在利用上面的查询信息当做条件,查询到需要的结果

mysql> select * from emp where (job,managerid) = (select job,managerid from emp where name="芳芳");
+----+--------+------+--------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+--------+------+--------+--------+------------+-----------+---------+
| 3 | 问问 | 22 | 开发 | 18000 | 2022-07-20 | 2 | 1 |
| 4 | 芳芳 | 22 | 开发 | 21000 | 2019-08-18 | 2 | 1 |
+----+--------+------+--------+--------+------------+-----------+---------+
2 rows in set (0.01 sec)

        说明1:这种子查询返回结果是一行数据的,就叫做行子查询

  8.7、表子查询

    8.7.1 概念:子查询返回的结果是多行多列,这种子查询称为表子查询

    8.7.2 常用的操作符:in

    8.7.3 使用场景:经常将查询到的结果当做一个临时表使用

    8.7.4 案例

      案例1:查询与芳芳的年龄和部门一样或者和娜娜年龄和部门一样的员工

        分析1:先查询出来芳芳的和年龄和部门以及娜娜的年龄和部门

mysql> select age,dept_id from emp where name = "芳芳" or name = "娜娜";
+------+---------+
| age | dept_id |
+------+---------+
| 22 | 1 |
| 25 | 3 |
+------+---------+
2 rows in set (0.00 sec)

        说明1:这次的查询结果仍然是一个多行多列的临时表

        分析2:将上述查询结果当做条件使用

mysql> select * from emp where(age,dept_id) in (select age,dept_id from emp where name="芳芳" or name="娜娜");
+----+--------+------+--------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+--------+------+--------+--------+------------+-----------+---------+
| 3 | 问问 | 22 | 开发 | 18000 | 2022-07-20 | 2 | 1 |
| 4 | 芳芳 | 22 | 开发 | 21000 | 2019-08-18 | 2 | 1 |
| 5 | 珊珊 | 22 | 开发 | 15000 | 2021-04-10 | 3 | 1 |
| 6 | 娜娜 | 25 | 财务 | 24000 | 2023-07-16 | 1 | 3 |
| 7 | 咔咔 | 25 | 出纳 | 8000 | 2021-07-10 | 6 | 3 |
+----+--------+------+--------+--------+------------+-----------+---------+
5 rows in set (0.00 sec)

      案例2:查询入职时间是“2020-01-01”之后的员工信息及部门信息

        分析1:先查询入职时间是“2020-01-01”之后的员工信息

mysql> select * from emp where entrydate > "2020-01-01";
+----+--------+------+--------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+--------+------+--------+--------+------------+-----------+---------+
| 3 | 问问 | 22 | 开发 | 18000 | 2022-07-20 | 2 | 1 |
| 5 | 珊珊 | 22 | 开发 | 15000 | 2021-04-10 | 3 | 1 |
| 6 | 娜娜 | 25 | 财务 | 24000 | 2023-07-16 | 1 | 3 |
| 7 | 咔咔 | 25 | 出纳 | 8000 | 2021-07-10 | 6 | 3 |
| 8 | 静静 | 27 | 人事 | 5000 | 2021-07-11 | 1 | NULL |
+----+--------+------+--------+--------+------------+-----------+---------+
5 rows in set (0.00 sec)

        分析2:在查询这部分员工对应的部门信息

mysql> select e.*, d.* from (select * from emp where entrydate > "2020-01-01") as e left join dept as d on e.dept_id=d.id;
+----+--------+------+--------+--------+------------+-----------+---------+------+-----------+
| id | name | age | job | salary | entrydate | managerid | dept_id | id | name |
+----+--------+------+--------+--------+------------+-----------+---------+------+-----------+
| 3 | 问问 | 22 | 开发 | 18000 | 2022-07-20 | 2 | 1 | 1 | 研发部 |
| 5 | 珊珊 | 22 | 开发 | 15000 | 2021-04-10 | 3 | 1 | 1 | 研发部 |
| 6 | 娜娜 | 25 | 财务 | 24000 | 2023-07-16 | 1 | 3 | 3 | 财务部 |
| 7 | 咔咔 | 25 | 出纳 | 8000 | 2021-07-10 | 6 | 3 | 3 | 财务部 |
| 8 | 静静 | 27 | 人事 | 5000 | 2021-07-11 | 1 | NULL | NULL | NULL |
+----+--------+------+--------+--------+------------+-----------+---------+------+-----------+
5 rows in set (0.00 sec)

        说明1:将自查询的结果当做一张临时表,与其他的表做连接查询

  

Mysql基础8-多表查询的更多相关文章

  1. mysql 基础入门 单表查询

    单表查询 select 表头,表头 as 别名 ,表头(+-*/的运算) from table_a 1.条件查询 where + 条件 <> , != 不等于 = 等于,也可以表示字符串值 ...

  2. mysql 数据操作 单表查询 目录

    mysql 数据操作 单表查询 mysql 数据操作 单表查询 简单查询 避免重复DISTINCT mysql 数据操作 单表查询 通过四则运算查询 mysql 数据操作 单表查询 concat()函 ...

  3. mysql 数据操作 多表查询 目录

    mysql 数据操作 多表查询 准备 多表连接查询介绍 mysql 数据操作 多表查询 多表连接查询 笛卡尔积 mysql 数据操作 多表查询 多表连接查询 内连接 mysql 数据操作 多表查询 多 ...

  4. MySQL数据库语法-多表查询练习一

    MySQL数据库语法-多表查询练习一 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客主要介绍的多表查询的外键约束,以及如何使用外链接和内连接查询数据信息. 一.数据表和测试 ...

  5. mysql 数据操作 单表查询 where 约束 目录

    mysql 数据操作 单表查询 where约束 between and or mysql 数据操作 单表查询 where约束 is null in mysql 数据操作 单表查询 where约束 li ...

  6. mysql 数据操作 单表查询 group by 分组 目录

    mysql 数据操作 单表查询 group by 介绍 mysql 数据操作 单表查询 group by 聚合函数 mysql 数据操作 单表查询 group by 聚合函数 没有group by情况 ...

  7. MySQL数据库之单表查询中关键字的执行顺序

    目录 MySQL数据库之单表查询中关键字的执行顺序 1 语法顺序 2 执行顺序 3 关键字使用语法 MySQL数据库之单表查询中关键字的执行顺序 1 语法顺序 select distinct from ...

  8. mysql中的回表查询与索引覆盖

    了解一下MySQL中的回表查询与索引覆盖. 回表查询 要说回表查询,先要从InnoDB的索引实现说起.InnoDB有两大类索引,一类是聚集索引(Clustered Index),一类是普通索引(Sec ...

  9. MySQL数据库语法-单表查询练习

    MySQL数据库语法-单表查询练习 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客主要是对聚合函数和分组的练习. 一.数据表和测试数据准备 /* @author :yinz ...

  10. mysql,SQL标准,多表查询中内连接,外连接,自然连接等详解之查询结果集的笛卡尔积的演化

    先附上数据. CREATE TABLE `course` ( `cno` ) NOT NULL, `cname` ) CHARACTER SET utf8 NOT NULL, `ctime` ) NO ...

随机推荐

  1. 基于Mongodb分布式锁简单实现,解决定时任务并发执行问题

    前言 我们日常开发过程,会有一些定时任务的代码来统计一些系统运行数据,但是我们应用有需要部署多个实例,传统的通过配置文件来控制定时任务是否启动又太过繁琐,而且还经常出错,导致一些异常数据的产生 网上有 ...

  2. 如何快速在手机中查看UDID,无需itunes、itools

      第一步:使用iPhone/iPad打开这个网页 http://www.appuploader.net/ 如果嫌麻烦也可以电脑打 http://www.appuploader.net/,之后会出现二 ...

  3. 密码学与网安——intro

    Terminology primitive: 原语 (一种不可分割的最基础操作,跟具体的视角和情形有关) 两个时间节点 1949年(1945年):Shannon 提出完全安全性,开始现代密码学 197 ...

  4. awk判断整除(包含小数和负数)

    awk判断整除常用的方法是用内置的int或者求余数的算符% 被整数整除 输出0-100之间能被9整除的整数 使用 num/9==int(num/9) 的判断方法可以很好实现. awk 'BEGIN{ ...

  5. Linux中重定向应注意的事情

    引言 你是否见过bash ... 2>&1 1>file.txt的写法? 还没发现这样的写法有什么问题? 那么恭喜你, 看完本文你又将学会一个新知识! 重定向的错误用法 以引言中命 ...

  6. [转] Windows下Hook DirectX

    首先说,这篇文章是很久以前为了玩成某游戏的HOOK找到的资料,虽然一直没用上,但是还是让我保留下来了.直接贴上了..看不懂也不要问我,我都没看. 也许看得懂的人对他们来说这是一个思路,不懂的就当垃圾文 ...

  7. 【python】使用爬虫爬取动漫之家漫画全部更新信息

    本篇仅在于交流学习 网站名称为: https://manhua.dmzj.com/ 1.首先将相应的库导入: import requests from lxml import etree 2.确定漫画 ...

  8. 2023-04-11:给你下标从 0 开始、长度为 n 的字符串 pattern , 它包含两种字符,‘I‘ 表示 上升 ,‘D‘ 表示 下降 。 你需要构造一个下标从 0 开始长度为 n + 1 的

    2023-04-11:给你下标从 0 开始.长度为 n 的字符串 pattern , 它包含两种字符,'I' 表示 上升 ,'D' 表示 下降 . 你需要构造一个下标从 0 开始长度为 n + 1 的 ...

  9. 2022-11-26:给定一个字符串s,只含有0~9这些字符 你可以使用来自s中的数字,目的是拼出一个最大的回文数 使用数字的个数,不能超过s里含有的个数 比如 : 39878,能拼出的最大回文数是

    2022-11-26:给定一个字符串s,只含有0~9这些字符 你可以使用来自s中的数字,目的是拼出一个最大的回文数 使用数字的个数,不能超过s里含有的个数 比如 : 39878,能拼出的最大回文数是 ...

  10. 2022-01-05:有四种诗的韵律分别为: AABB、ABAB、ABBA、AAAA。 比如 : 1 1 3 3就属于AABB型的韵律、

    2022-01-05:有四种诗的韵律分别为: AABB.ABAB.ABBA.AAAA. 比如 : 1 1 3 3就属于AABB型的韵律.6 6 6 6就属于AAAA型的韵律等等, 一个数组arr,当然 ...