数据库之六 多表查询

【零】准备数据

【1】创建表

(1)部门表
  • id是部门的编号
  • name是部门的名字
# 确保表不存在
drop table if exists department;
# 创建表
create table department(
id int auto_increment primary key,
name varchar(6)
)auto_increment = 501 ;
(2)创建员工表
  • id是员工的编号
  • name是员工的姓名
  • sex是员工性别默认男性
  • department_id是所在部门的编号
# 确保表不存在
drop table if exists employee;
# 创建表
create table employee(
id int auto_increment primary key,
name varchar(10),
sex enum('female', 'male') default 'male',
department_id int
);

【2】插入数据

(1)部门信息
  • 只插入3个部门信息
insert department (name) values("销售部"), ("技术部"), ("售后部");
+-----+-----------+
| id  | name      |
+-----+-----------+
| 501 | 销售部    |
| 502 | 技术部    |
| 503 | 售后部    |
+-----+-----------+
(2)员工信息
  • 共5名员工

  • 有一个员工的部门信息为505

  • 其他员工信息均正常,但是没有503

insert employee (name, sex, department_id)values
('John', 'male', 501),
('Jane', 'female', 502),
('Mike', 'male', 502),
('Tom', 'male', 505),
('Amy', 'female', 501);
+----+------+--------+---------------+
| id | name | sex    | department_id |
+----+------+--------+---------------+
|  1 | John | male   |           501 |
|  2 | Jane | female |           502 |
|  3 | Mike | male   |           502 |
|  4 | Tom  | male   |           505 |
|  5 | Amy  | female |           501 |
+----+------+--------+---------------+

【一】子查询

【1】说明

  • 子查询是指在SQL语句中嵌套了另一个完整的查询语句。
  • 子查询可以用于检索满足外部查询条件的数据,或者用于提供外部查询的条件。
  • 还可以说是将一个查询语句的结果当做另外一个查询语句的条件去用。

【2】示例

(1)查询Jane所在的部门名称
  • 先查看Jane的部门名称
select department_id
from employee
where name='Jane';
+---------------+
| department_id |
+---------------+
|           502 |
+---------------+
  • 在查询502的部门名字
select name 
from department
where id=502;
+-----------+
| name      |
+-----------+
| 技术部    |
+-----------+
  • 整合嵌套
select name
from department
where id in (
select department_id
from employee
where name='Jane');
select name
from department
where id = (
select department_id
from employee
where name='Jane');
+-----------+
| name      |
+-----------+
| 技术部    |
+-----------+
(2)查看技术部和售后部的员工信息
  • 先查看技术部和售后部的部门id
select id
from department
where name in ('技术部', '销售部');
+-----+
| id  |
+-----+
| 501 |
| 502 |
+-----+
  • 查看部门id是501和502的员工信息
select *
from employee
where department_id in (501, 502);
+----+------+--------+---------------+
| id | name | sex    | department_id |
+----+------+--------+---------------+
|  1 | John | male   |           501 |
|  2 | Jane | female |           502 |
|  3 | Mike | male   |           502 |
|  5 | Amy  | female |           501 |
+----+------+--------+---------------+
  • 整合嵌套
select *
from employee
where department_id in(
select id
from department
where name in ("技术部", "销售部"));
+----+------+--------+---------------+
| id | name | sex    | department_id |
+----+------+--------+---------------+
|  1 | John | male   |           501 |
|  2 | Jane | female |           502 |
|  3 | Mike | male   |           502 |
|  5 | Amy  | female |           501 |
+----+------+--------+---------------+

【二】联表查询

  • 联表查询是在SQL中一种常用的操作,用于同时从多个表中检索数据,通过表之间的关联条件将它们连接在一起。
  • 联表查询允许我们在一个查询中使用多个表的数据,以便获取更全面的信息。

【1】拼表 cross join

  • 语法
from 表1 corss join 表2 on 条件
from 表1, 表2 on 条件;
(0)笛卡尔积
  • 笛卡尔积是一个数学概念,它描述的是两个集合之间所有可能的元素组合的数量。
  • 具体来说,如果集合A有n个元素,集合B有m个元素,则它们的笛卡尔积的大小为nm。
(1)显示的交叉连接
  • cross join
select *
from employee
cross join department;
(2)隐式的交叉连接
  • 逗号
select *
from employee, department;
(3)结果
  • 部门表有3个
  • 员工表有5个
  • 所以最终经过笛卡尔积的运算(3*5)有15个组合,即15个结果
+----+------+--------+---------------+-----+-----------+
| id | name | sex    | department_id | id  | name      |
+----+------+--------+---------------+-----+-----------+
|  1 | John | male   |           501 | 501 | 销售部    |
|  1 | John | male   |           501 | 502 | 技术部    |
|  1 | John | male   |           501 | 503 | 售后部    |
|  2 | Jane | female |           502 | 501 | 销售部    |
|  2 | Jane | female |           502 | 502 | 技术部    |
|  2 | Jane | female |           502 | 503 | 售后部    |
|  3 | Mike | male   |           502 | 501 | 销售部    |
|  3 | Mike | male   |           502 | 502 | 技术部    |
|  3 | Mike | male   |           502 | 503 | 售后部    |
|  4 | Tom  | male   |           505 | 501 | 销售部    |
|  4 | Tom  | male   |           505 | 502 | 技术部    |
|  4 | Tom  | male   |           505 | 503 | 售后部    |
|  5 | Amy  | female |           501 | 501 | 销售部    |
|  5 | Amy  | female |           501 | 502 | 技术部    |
|  5 | Amy  | female |           501 | 503 | 售后部    |
+----+------+--------+---------------+-----+-----------+
(4)拼表进阶
  • 我们想得到的仅仅是员工表和部门对应上的结果
  • 并不想要全部的结果
  • 所以可以添加额外的条件
# 隐式交叉连接
select *
from employee, department
where employee.department_id = department.id;
# 显示交叉连接
select *
from employee
cross join department
where employee.department_id = department.id;
+----+------+--------+---------------+-----+-----------+
| id | name | sex    | department_id | id  | name      |
+----+------+--------+---------------+-----+-----------+
|  1 | John | male   |           501 | 501 | 销售部    |
|  2 | Jane | female |           502 | 502 | 技术部    |
|  3 | Mike | male   |           502 | 502 | 技术部    |
|  5 | Amy  | female |           501 | 501 | 销售部    |
+----+------+--------+---------------+-----+-----------+
  • 少了4号员工
    • 因为4号员工的部门id找不到对应的部门

【2】内连接 inner join

  • 语法
from 表1 inner join 表2 on 条件
(1)说明
  • 内连接返回两个表中满足连接条件的行
  • 只拼接两张表中共有的数据部分
(2)示例
select *
from employee
inner join department
on employee.department_id = department.id; 
+----+------+--------+---------------+-----+-----------+
| id | name | sex    | department_id | id  | name      |
+----+------+--------+---------------+-----+-----------+
|  1 | John | male   |           501 | 501 | 销售部    |
|  2 | Jane | female |           502 | 502 | 技术部    |
|  3 | Mike | male   |           502 | 502 | 技术部    |
|  5 | Amy  | female |           501 | 501 | 销售部    |
+----+------+--------+---------------+-----+-----------+
  • 结果和拼表进阶一样

【3】左连接 left join(常用)

  • 语法
from 表1 left join 表2 on 条件
(1)说明
  • 左连接返回左表中的所有行,以及与右表中满足连接条件的行。
  • 如果右表中没有匹配的行,则返回NULL。
(2)示例
select *
from employee
left join department
on employee.department_id = department.id;
+----+------+--------+---------------+------+-----------+
| id | name | sex    | department_id | id   | name      |
+----+------+--------+---------------+------+-----------+
|  1 | John | male   |           501 |  501 | 销售部    |
|  5 | Amy  | female |           501 |  501 | 销售部    |
|  2 | Jane | female |           502 |  502 | 技术部    |
|  3 | Mike | male   |           502 |  502 | 技术部    |
|  4 | Tom  | male   |           505 | NULL | NULL      |
+----+------+--------+---------------+------+-----------+
  • 4号员工的部门信息不存在
  • 所以用NULL表示

【4】右连接 right join

  • 语法
from 表1 right join 表2 on 条件
(1)说明
  • 右连接返回右表中的所有行,以及与左表中满足连接条件的行。
  • 如果左表中没有匹配的行,则返回NULL。
(2)示例
select *
from employee
right join department
on employee.department_id = department.id;
+------+------+--------+---------------+-----+-----------+
| id   | name | sex    | department_id | id  | name      |
+------+------+--------+---------------+-----+-----------+
|    1 | John | male   |           501 | 501 | 销售部    |
|    2 | Jane | female |           502 | 502 | 技术部    |
|    3 | Mike | male   |           502 | 502 | 技术部    |
|    5 | Amy  | female |           501 | 501 | 销售部    |
| NULL | NULL | NULL   |          NULL | 503 | 售后部    |
+------+------+--------+---------------+-----+-----------+
  • 售后部没有员工存在
  • 所以用NULL表示

【5】全连接 union

  • 语法
select *
from 表1
left join 表2
on 条件
union all
select *
from 表1
right join 表2
on 条件
(1)说明
  • 全连接返回左表和右表中的所有行。
  • 如果没有匹配的行,则用NULL填充缺失的部分。
  • 注意UNION 会自动去重,如果你想保留所有行,包括重复的行,可以使用 UNION ALL
(2)示例
select * 
from employee
left join department
on employee.department_id = department.id 
union
select *
from employee
right join department
on employee.department_id = department.id;
+------+------+--------+---------------+------+-----------+
| id   | name | sex    | department_id | id   | name      |
+------+------+--------+---------------+------+-----------+
|    1 | John | male   |           501 |  501 | 销售部    |
|    5 | Amy  | female |           501 |  501 | 销售部    |
|    2 | Jane | female |           502 |  502 | 技术部    |
|    3 | Mike | male   |           502 |  502 | 技术部    |
|    4 | Tom  | male   |           505 | NULL | NULL      |
| NULL | NULL | NULL   |          NULL |  503 | 售后部    |
+------+------+--------+---------------+------+-----------+
  • 售后部没有员工存在,所以用NULL表示
  • 4号员工的部门id存在对应部门,所以用NULL表示
  • 20
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值