当前位置: 首页 > news >正文

【MySQL | 基础】多表查询

前文回顾:约束

文章目录

1.多表关系

1.1一对多(多对一)

1.2 多对多关系

1.3 一对一关系

2. 多表查询概述

2.1 多表查询的分类

2.2.1连接查询

2.1.2 字查询

3.内连接

3.1 内连接查询语法

3. 2 代码演示

4. 外连接

4.1 外连接语法

4.2 代码演示

5. 自连接

5.1 自连接语法

5. 2 代码演示

6. 联合查询

7. 子查询

7.1 子查询分类

7.1.1 标量子查询

7.1.2 列子查询

7.1.3 行子查询

7.1.4 表子查询

8. 练习

9.此文章用到的表数据


说明:本文章代码演示和练习使用到的数据表在本文章最后

1.多表关系

        项目开发中,进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结构,以各个表结构之间有存在着各种联系,基本上分为三种:

  • 一对多(多对一)
  • 多对多
  • 一对一

1.1一对多(多对一)

  • 案例:部门 与 员工的关系
  • 关系:一个部门对应多个员工,一个员工对应一个部门
  • 实现:在多的一方建立外键,指向一的一方的主键

1.2 多对多关系

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

create table student(
id int auto_increment primary key comment '主键ID',
name varchar(10) comment '姓名',
no varchar(10) comment'学号,'
)comment'学生表';
insert into student values (null,'黛绮丝','2000100101'),(null,'谢逊','2000100102'),(null,'般天正','2000100103'),(null,'韦一笑','2000100104');create table course(
id int auto_increment primary key comment '主键ID',
name varchar(10) comment '课程名称'
)comment '课程表';
insert into course values (null,'Java'), (null,'PHP'), (null,'MySL') ,(null,'Hadoop');create table student_course(
id int auto_increment comment '主键' primary key,
studentid int not null comment '学生ID!',
courseid int not null comment '课程',
constraint fk_courseid foreign key (courseid)
references course (id),
constraint fk_studentid foreign key (studentid)references student (id)
)comment '学生课程中间表';
insert into student_course values (null,1,1),(null,1,2),(null,1,3),(null,2,2),(null,2,3),(null,3,4);

1.3 一对一关系

  • 案例:用户 与 用户 详情的关系
  • 关系:一对一关系,多用于单表的拆分,将一张表的基础字段放在一张中,其他详细字段放在另一张表中,以提升操作效率
  • 实现:在任意的一方加入外键,关联另一方的主键,并且设置外键为唯一的(UNIQUE)

CREATE TABLE tb_user (id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',name VARCHAR(10) COMMENT '姓名',age INT COMMENT '年龄',gender CHAR(1) COMMENT '1: 男, 2: 女',phone CHAR(11) COMMENT '手机号'
) COMMENT '用户基本信息表';CREATE TABLE tb_user_edu (id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',degree VARCHAR(20) COMMENT '学历',major VARCHAR(50) COMMENT '专业',primaryschool VARCHAR(50) COMMENT '小学',middleschool VARCHAR(50) COMMENT '中学',university VARCHAR(50) COMMENT '大学',userid INT UNIQUE COMMENT '用户ID',CONSTRAINT fk_userid FOREIGN KEY (userid) REFERENCES tb_user(id)
) COMMENT '用户教育信息表';INSERT INTO tb_user(id, name, age, gender, phone) VALUES(NULL, '黄渤', 45, '1', '18800011111'),(NULL, '冰冰', 35, '2', '18800022222'),(NULL, '马云', 55, '1', '18800088888'),(NULL, '李彦宏', 50, '1', '18800099999');INSERT INTO tb_user_edu(id, degree, major, primaryschool, middleschool, university, userid) VALUES(NULL, '本科', '舞蹈', '静安区第一小学', '静安区第一中学', '北京舞蹈学院', 1),(NULL, '硕士', '表演', '朝阳区第一小学', '朝阳区第一中学', '北京电影学院', 2),(NULL, '本科', '英语', '杭州市第一小学', '杭州市第一中学', '杭州师范大学', 3),(NULL, '本科', '应用数学', '阳泉区第一小学', '阳泉区第一中学', '清华大学', 4);

2. 多表查询概述

  • 概述:指的是从多张表中查询数据
  • 笛卡尔积:笛卡尔积是指在数学中,两个集合A 和 集合B的所有组合情况(在多表查询时,需要消除无效的笛卡尔积)比如:R 表和 T进行笛卡尔积运算 得到的结果行数等于 T行数 乘以 S行数,列数等于T列数 加 S列数。

所需要的数据表在文章最后准备数据数据中

-- 多表查询 -- 笛卡尔积
select * from emp,dept;-- 消除无效的笛卡尔积
select * from emp,dept where emp.dept_id = dept.id ORDER BY emp.id;  -- 发现查询到了16 条数据,原因id为17的员工没有分配部门,部门为null。

2.1 多表查询的分类

2.2.1连接查询

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

2.1.2 字查询

3.内连接

注意:内连接连接的是两张表交集部分。

3.1 内连接查询语法

隐式内连接

SELECT 字段列表 FROM 表1, 表2 WHERE 条件...;

显示内连接

SELECT 字段列表 FROM 表1 [INNER] JOIN 表2 ON 连接条件...; 

3. 2 代码演示

-- 内连接演示
-- 1. 查询每一个员工的姓名,以及关联的部门的名称(隐式内链接)
-- 表结构 : emp, dept
-- 连接条件: emp.dept_id = dept.id
select emp.name as 姓名, dept.name as 部门 from emp, dept where emp.dept_id = dept.id; -- 给表起一个别名(注意:如果起了别名就不能再使用别名,原来的名字就不能使用了)
select e.name as 姓名, d.name as 部门 from emp e, dept d where e.dept_id = d.id; -- 2. 查询每一个员工的姓名,以及关联的部门的名称(显示内链接)
-- 表结构 : emp, dept
-- 连接条件: emp.dept_id = dept.id
select emp.name as 姓名, dept.name as 部门 from emp inner join dept on emp.dept_id = dept.id;

4. 外连接

4.1 外连接语法

左外连接

SELECT 字段列表 FROM 表1 LEFT [OUTER] JOIN 表2 ON 条件...;

注意左外连接相当于查询表1(左表)的所有数据 包含 表1和表2交集部分的数据

右外连接

SELECT 字段列表 FROM 表1 RIGHT [OUTER] JOIN 表2 ON 条件...;

 注意右外连接相当于查询表2(右表)的所有数据 包含 表1和表2交集部分的数据

4.2 代码演示

-- 外连接演示
-- 1、查询emp表的所有数据,和对应的部门信息(左外连接)
-- 表结构: emp, dept
-- 连接条件:emp.dept_id = dept.id
select e.*,d.name from emp e left outer join dept d on e.dept_id = d.id; 
select e.*,d.name from emp e left join dept d on e.dept_id = d.id; -- 2、查询dept表的所有数据,和对应的员工信息(右外连接)
select d.*,e.* from emp e right outer join dept d on e.dept_id = d.id;
select d.*,e.* from dept d left outer join emp e on e.dept_id = d.id;

5. 自连接

  • 自连接:当前表自身的连接查询,自连接必须使用表别名

5.1 自连接语法

SELECT 字段列表 FROM 表A  别名A   JOIN  表B  别名B  ON  条件...;

注意:自连接查询,可以是内连接查询也可以是外连接查询

5. 2 代码演示

-- 自连接
-- 1、查询 员及其所属领导名字
-- 表结构:emp表
-- emp表中managerid所属领导的id
select e1.name,e2.name as 领导 from emp e1 inner join emp e2 on e1.managerid = e2.id;-- 2.查询所有员工emp 以及领导的名字emp 如果员工没有领导也需要查询出来
select e1.name 员工, e2.name 领导 from emp e1 left outer join emp e2 on e1.managerid = e2. id;

6. 联合查询

  • 联合查询设计到的两个关键字:union, union  all
  • 对于联合查询,就是把多次查询结果合并一起,形成一个新的查询结果集。
  • 注意
    • 对于联合查询的多张表的列数必须保持一致,字段类型也需要保持一致。 
    • union all 会将全部的数据直接合并在一起,union会对合并之后的数据去重

SELECT  字段列表   FROM  表A ...

UNION [ALL]

SELECT  字段列表   FROM  表B ...;

-- union all, union
-- 联合查询
-- 1、将薪资低于 5000 的员工,和 年龄大于 50 岁的员工全部查询出来。
select * from emp where salary < 5000
union all 
select * from emp where age > 50;-- 去重只需要把all去掉即可
select * from emp where salary < 5000
union  
select * from emp where age > 50;select * from emp where salary < 5000 or age > 50;

7. 子查询

概念:SQL语句中嵌套SELECT语句,称为嵌套查询,又称子查询

SELECT * FROM  表1  WHERE  字段名 = (SELECT 字段名  FROM 表2);

注意:子查询外部的语句可以是INSERT、UPDATE、DELETE、SELECT 的任何一个。

7.1 子查询分类

根据子查询结果不同,分为:

  • 标量子查询(子查询的结果为单值)
  • 列子查询(子查询结果为一列)
  • 行子查询(子查询结构为一行)
  • 表子查询(子查询结果为多行多列)

根据子查询位置,分为:WHERE之后,FROM之后、SELECT之后。

7.1.1 标量子查询

  • 标量子查询:子查询返回结果是单个值(数字、字符串、日期),最简单的形式,这种子查询称为标量子查询
  • 常用的操作符号:=   <>   <   <=   >  >= 
-- 标量子查询
-- 1、查询“销售部”的所有员工信息
--  拆分题目:
--  a:查询“销售部”部门ID
select id from dept where name = '销售部';
--  b: 根据销售部门id查询员工信息
select * from emp where dept_id = 4;-- 子查询查询如下:
select * from emp where dept_id = (select id from dept where name = '销售部') -- 2、查询在“方东白”入职之后的员工信息
select * from emp where entrydate > (select entrydate from emp where name = '方东白');

7.1.2 列子查询

  • 列子查询:子查询返回的结果是一列(可以是多行),这种子查询称为列子查询
  • 常用的操作符:IN、NOT IN、ANY、SOME、ALL
操作符描述
IN在指定范围之内,多选一
NOT IN不在指定的集合范围内
ANY子查询返回列表中,有任意一个满足即可
SOME与ANY等同,使用SOME的地方都可以使用ANY
ALL子查询返回列表的所有值都必须满足
-- 列子查询
-- 1、查询”销售部“和“市场部”的所有员工信息
-- a:查询”销售部“和“市场部”的部门id
select id from dept where name = '销售部' or name = '市场部';
-- b:根据部门id,查询员工信息
select * from emp where dept_id in (2, 4);select * from emp where dept_id in (select id from dept where name = '销售部' or name = '市场部');-- 2、查询比 财务部 所有人工资都高的员工信息
-- a:查询所有财务部人员工资
select salary from emp where dept_id = (select id from dept where name = '财务部');
-- b:查询比”财务部“薪资都高的员工信息
select * from emp where salary > all(select salary from emp where dept_id = (select id from dept where name = '财务部'));-- 方式2:
select * from emp where salary > (select max(salary) from emp where dept_id = (select id from dept where name = '财务部'));-- 3、查询比“研发部”其中任意一人工资高的员工信息
-- a:查询研发部门所有人的工资
select salary from emp where dept_id = (select id from dept where name = '研发部');
-- b:比“研发部”任意一人工资要高的员工信息
select * from emp where salary > any(select salary from emp where dept_id = (select id from dept where name = '研发部'));-- 方式2
select * from emp where salary > some(select salary from emp where dept_id = (select id from dept where name = '研发部'));
-- 方式3
select * from emp where salary > (select min(salary) from emp where dept_id = (select id from dept where name = '研发部'));

7.1.3 行子查询

  • 行子查询:子查询返回的结果是一行(可以是多列),这种子查询称为行子查询
  • 常用的操作法:= 、<>、IN、NOT IN
-- 行子查询
-- 1、查询与“张无忌”的薪资及直属领导相同的员工信息
-- a:查询与“张无忌”的薪资及直属领导
select salary, managerid from emp where name = '张无忌';
-- b:查询与“张无忌”的薪资及直属领导相同的员工信息
select * from emp where (salary,managerid) = (select salary, managerid from emp where name = '张无忌');

7.1.4 表子查询

  • 表子查询:子查询返回的结果是多行多列,这种子查询称为表子查询
  • 常用的操作符:IN
-- 表子查询
-- 1、查询与“鹿杖客”,“宋远桥”职位和薪资相同的员工信息
-- a:查询与“鹿杖客”,“宋远桥”职位和薪资
select job, salary from emp where name = '鹿杖客' or name = '宋远桥';
-- b:查询与“鹿杖客”,“宋远桥”职位和薪资相同的员工信息
select * from emp where (job,salary) in (select job, salary from emp where name = '鹿杖客' or name = '宋远桥');-- 2、查询入职日期是“2006-01-01”之后的员工信息,及其部门
-- a:查询入职日期是“2006-01-01”之后的员工信息
select * from emp where entrydate > '2006-01-01';
-- b:查询这部分员工,对应的部门信息
select * from (select * from emp where entrydate > '2006-01-01') e left outer join dept d on e.dept_id = d.id;-- 方式2
select * from emp e left outer join dept d on e.dept_id = d.id where entrydate > '2006-01-01';

8. 练习

-- 1、查询员工的姓名,年龄,职位,部门信息(隐式查询)
-- 表:emp 、dept
-- emp.dept_id = dept.id
select e.name,age,job,d.name from emp e, dept d where e.dept_id = d.id;
select e.name,age,job,d.name from emp e inner join dept d on e.dept_id = d.id; -- 显示内连接-- 2、查询年龄小于30岁的员工的姓名,年龄,职位,部门信息(显示内连接)
-- 表:emp 、dept
-- emp.dept_id = dept.id
select e.name,age,job,d.name from emp e inner join dept d on e.dept_id = d.id where age < 30;-- 3、查询拥有员工的部门ID 、部门名称
-- 表:emp 、dept
-- emp.dept_id = dept.id
select distinct dept_id,d.name from emp e inner join dept d on e.dept_id = d.id;-- 4、查询所有年龄大于40岁的员工,以其归属的部门名称,如果员工没有分配部门,也需要显示出来
-- 表:emp 、dept
-- emp.dept_id = dept.id
-- 外连接
select e.*,d.name from emp e left outer join dept d on e.dept_id = d.id where age > 40;-- 5、查询所有员工资等级
-- 表:emp、salgrade 
-- 连接条件:emp.salary >= salgrade.losal and emp.salary <= salgrade.hisal
select e.*,s.grade 薪资等级 from emp e ,salgrade s where salary >= losal and salary <= s.hisal;
select e.*,s.grade 薪资等级 from emp e ,salgrade s where salary between s.losal and s.hisal;-- 6、查询“研发部”所有员工的信息以及 工资等级
-- 表:emp、dept、salgrade 
-- 连接条件:emp.dept_id dept.id and e.salary between s.losal and s.hisal
-- 查询条件:dept.name = '研发部'
select e.*,s.grade from emp e,salgrade s, dept d where e.dept_id = d.id  and e.salary between s.losal and s.hisal and d.name = '研发部';-- 7、查询“研发部”员工的平均工资
-- 表:emp.dept 
-- 连接条件:e.dept_id = d.id
-- 查询条件:d.name = '研发部'
select avg(salary) from emp e,dept d where e.dept_id = d.id and d.name = '研发部';-- 8、查询工资比“灭绝”高的员工信息
-- 子查询
select * from emp where salary > (select salary from emp where name = '灭绝');
-- 自身连接
select e1.* from emp e1, emp e2 where e2.name = '灭绝' and e1.salary > e2.salary;-- 9、查询比平均薪资高的员工信息
-- 子查询
select * from emp where salary > (select avg(salary) from emp);-- 10、查询低于本部门平均工资的员工信息
-- a: 查询指定部门平均薪资
select avg(e1.salary) from emp e1 where e1.dept_id = 1;
select avg(e1.salary) from emp e1 where e1.dept_id = 2;
-- b:查询低于本部门平均工资的员工信息
select * from emp e2 where e2.salary < (select avg(e1.salary) from emp e1 where e1.dept_id = e2.dept_id);-- 11、查询所有的部门信息,并统计部门的员工人数
-- a:查询所以部门信息
select * from dept;
-- b:统计每个部门的员工人数
select count(*) from emp where dept_id = 1;
-- 合并上面两部
select d.id, d.name ,(select count(*) from emp e where e.dept_id = d.id) from dept d-- 12、查询所有学生的选课情况,展示出学生名称,学号,课程名称
-- 表:student,course、sc
-- 连接条件:s.id = sc.studentid and s.id = sc.courseid
select s.name,no,c.name from student s ,course c, student_course sc where s.id = sc.studentid and c.id = sc.courseid;

9.此文章用到的表数据

多表查询代码演示以及练习数据

create table dept(id int primary key auto_increment,name varchar(10)
);insert into dept values(null, '研发部'),(null, '市场部'),(null, '财务部'),(null, '销售部'),(null, '总经办'),(null, '人事部');create table emp(id int primary key auto_increment,name varchar(10),age int,job varchar(10),salary int,entrydate date,managerid int,dept_id int,constraint fk_dept foreign key (dept_id) references dept(id)
);insert into emp values(null, '金庸', 66, '总裁', 20000, '2000-01-01', null, 5),(null, '张无忌', 20, '项目经理', 12500, '2005-12-05', 1, 1),(null, '杨逍', 33, '开发', 8400, '2000-11-03', 2, 1),(null, '韦一笑', 48, '开发', 11000, '2002-02-05', 2, 1),(null, '常遇春', 43, '开发', 10500, '2004-09-07', 3, 1),(null, '小昭', 19, '程序员鼓励师', 6600, '2004-10-12', 2, 1),(null, '灭绝', 60, '财务总监', 8500, '2002-09-12', 1, 3),(null, '周芷若', 19, '会计', 4800, '2006-06-02', 7, 3),(null, '丁敏君', 23, '出纳', 5250, '2009-05-13', 7, 3),(null, '赵敏', 20, '市场部总监', 12500, '2004-10-12', 1, 2),(null, '鹿杖客', 56, '职员', 3750, '2006-10-03', 10, 2),(null, '鹤笔翁', 19, '职员', 3750, '2007-05-09', 10, 2),(null, '方东白', 19, '职员', 5500, '2009-02-12', 10, 2),(null, '张三丰', 88, '销售总监', 14000, '2004-10-12', 1, 4),(null, '俞莲舟', 38, '销售', 4600, '2004-10-12', 14, 4),(null, '宋远桥', 40, '销售', 4600, '2004-10-12', 14, 4),(null, '陈友谅', 42, null, 2000, '2011-10-12', 1, null);
create table salgrade(grade int,losal int,hisal int
) comment'薪资等级表';insert into salgrade
values (1, 0, 3000),(2, 3001, 5000),(3, 5001, 8000),(4, 8001, 10000),(5, 10001, 15000),(6, 15001, 20000),(7, 20001, 25000),(8, 25001, 30000);

多表查询联系第12题所需要的表

create table student(
id int auto_increment primary key comment '主键ID',
name varchar(10) comment '姓名',
no varchar(10) comment'学号,'
)comment'学生表';
insert into student values (null,'黛绮丝','2000100101'),(null,'谢逊','2000100102'),(null,'般天正','2000100103'),(null,'韦一笑','2000100104');create table course(
id int auto_increment primary key comment '主键ID',
name varchar(10) comment '课程名称'
)comment '课程表';
insert into course values (null,'Java'), (null,'PHP'), (null,'MySL') ,(null,'Hadoop');create table student_course(
id int auto_increment comment '主键' primary key,
studentid int not null comment '学生ID!',
courseid int not null comment '课程',
constraint fk_courseid foreign key (courseid)
references course (id),
constraint fk_studentid foreign key (studentid)references student (id)
)comment '学生课程中间表';
insert into student_course values (null,1,1),(null,1,2),(null,1,3),(null,2,2),(null,2,3),(null,3,4);

10. 小结

http://www.dtcms.com/a/618558.html

相关文章:

  • 网站建设评比自评情况网站没有收录从哪开始做优化
  • SATA协议深度剖析:从接口到指令集
  • 《嵌入式操作系统》_移植三星原版uboot20251114
  • 云南省和城乡建设厅网站环保空调东莞网站建设
  • 做鞋子网站的域名高端建站设计
  • Android内核进阶之周期更新PCM状态snd_pcm_period_elapsed:用法实例(九十二)
  • 做外汇关注的网站大学生创业做网站的筹资方式
  • HttpServletResponse 与 ResponseEntity 详解
  • 网络安全 | 深入了解OAuth 2.0原理
  • 人人商城网站开发wordpress图片放大镜
  • 2016年软件评测师,web测试案例分析解答
  • Vue 项目实战《尚医通》,获取挂号医生的信息展示,笔记43
  • wordpress创建多站点互联网公司排名伊对排第几
  • 什么网站容易做流量中小微企业名录查询系统
  • 杂志社网站模板wordpress网址导航模板
  • RAG 场景中常用的向量索引
  • 【论文阅读】Harnessing the Power of LLMs in Practice: A Survey on ChatGPT and Beyond
  • LC144 二叉树的前序遍历
  • Map的遍历方式
  • 有没有找人做标书的网站建网站用自己的主机做服务器
  • Day18:二叉树part8(669.修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树)
  • 常见的简单的营销软件宁波seo哪家最便宜
  • 电力系统设备故障因果推理与深度学习驱动的根因分析优化
  • ElasticSearch详解(篇二)
  • 重庆网站建设怎么样来个手机能看的网站2021
  • 网站建设的财务分析wordpress阶梯插件
  • CSS Position(定位)
  • redis安装与部署
  • 做网站的毕业设计做网站用什么语言高效
  • 长春好的做网站公司排名软件推广公司