MySQL(五)——多表查询

news2024/11/28 8:30:44

上期文章

MySQL(四)——约束


文章目录

  • 上期文章
  • 多表关系
    • 一对多(多对一)
    • 多对多
    • 多表外键关系可视化
    • 一对一
  • 多表查询概述
    • 笛卡尔积
    • 多表查询分类
      • 连接查询
  • 内连接
    • 隐式内连接
    • 显式内连接
  • 外连接
    • 左外连接
    • 右外连接
  • 自连接
  • 联合查询 union,union all
  • 子查询
    • 标量子查询
    • 列子查询
    • 行子查询
    • 表子查询
  • 多表查询案例
  • 总结
    • 多表关系
    • 多表查询


多表关系

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

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

一对多(多对一)

一个部门对应多个员工,一个员工对应一个部门
实现:在多的一方建立外键,指向一的一方的主键
在这里插入图片描述

多对多

一个学生可以选修多门课程,一门课程也可以供多个学生选择
实现:建立第三张中间表,中间表至少包含两个外键,分别关联两方主键
在这里插入图片描述

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 , 'MySQL') , (null, 'Hadoop');

create table student_course(
    id int auto_increment comment '主键' primary key,
    studentid int not null comment '学生ID',
    courseid int not null comment '课程ID',
    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);

多表外键关系可视化

在这里插入图片描述
在这里插入图片描述

一对一

一对一关系,多用于单表拆分,将一张表的基础字段放在一张表中,其他详情字段放在另一张表中,以提升操作效率
实现:在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的(UNQUE)
在这里插入图片描述

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','18800001111'), (null,'冰冰',35,'2','18800002222'), (null,'码云',55,'1','18800008888'), (null,'李彦宏',50,'1','18800009999');
insert into tb_user_edu(id, degree, major, primaryschool, middleschool,
university, userid) values
(null,'本科','舞蹈','静安区第一小学','静安区第一中学','北京舞蹈学院',1), (null,'硕士','表演','朝阳区第一小学','朝阳区第一中学','北京电影学院',2), (null,'本科','英语','杭州市第一小学','杭州市第一中学','杭州师范大学',3), (null,'本科','应用数学','阳泉第一小学','阳泉区第一中学','清华大学',4);

多表查询概述

create table dept(
id int auto_increment comment 'ID' primary key,
name varchar(50) not null comment '部门名称'
)comment '部门表';
INSERT INTO dept (id, name) VALUES (1, '研发部'), (2, '市场部'),(3, '财务部'), (4, '销售部'), (5, '总经办'), (6, '人事部');

create table emp(
id int auto_increment comment 'ID' primary key,
name varchar(50) not null comment '姓名',
age int comment '年龄',
job varchar(20) comment '职位',
salary int comment '薪资',
entrydate date comment '入职时间',
managerid int comment '直属领导ID',
dept_id int comment '部门ID'
)comment '员工表';
INSERT INTO emp (id, name, age, job,salary, entrydate, managerid, dept_id)
VALUES
(1, '金庸', 66, '总裁',20000, '2000-01-01', null,5),(2, '张无忌', 20, '项目经理',12500, '2005-12-05', 1,1),
(3, '杨逍', 33, '开发', 8400,'2000-11-03', 2,1),(4, '韦一笑', 48, '开发',11000, '2002-02-05', 2,1),
(5, '常遇春', 43, '开发',10500, '2004-09-07', 3,1),(6, '小昭', 19, '程序员鼓励师',6600, '2004-10-12', 2,1),
(7, '灭绝', 60, '财务总监',8500, '2002-09-12', 1,3), (8, '周芷若', 19, '会计',48000, '2006-06-02', 7,3),
(9, '丁敏君', 23, '出纳',5250, '2009-05-13', 7,3),
(10, '赵敏', 20, '市场部总监',12500, '2004-10-12', 1,2), (11, '鹿杖客', 56, '职员',3750, '2006-10-03', 10,2), (12, '鹤笔翁', 19, '职员',3750, '2007-05-09', 10,2), (13, '方东白', 19, '职员',5500, '2009-02-12', 10,2), (14, '张三丰', 88, '销售总监',14000, '2004-10-12', 1,4), (15, '俞莲舟', 38, '销售',4600, '2004-10-12', 14,4), (16, '宋远桥', 40, '销售',4600, '2004-10-12', 14,4), (17, '陈友谅', 42, null,2000, '2011-10-12', 1,null);

alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id);

笛卡尔积

select * from emp,dept;

102条结果
在这里插入图片描述
笛卡尔积:在数学中,两个集合A集合和B集合的所有组合情况,在多表查询时,需要消除无效的笛卡尔积
在这里插入图片描述

select * from emp,dept where emp.dept_id = dept.id order by emp.id;

多表查询分类

连接查询

内连接:相当于查询A、B交集部分数据
外连接:

  • 左外连接:查询左表所有数据,以及两张表交集部分数据
  • 右外连接:查询右表所有数据,以及两张表交集部分数据

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

内连接

隐式内连接

SELECT 字段列表 FROM1,2 WHERE 条件...;
select emp.name,dept.name from emp,dept where emp.dept_id = dept.id;

/*表起了别名之后只能使用别名*/
select e.name,d.name from emp e,dept d where e.dept_id = d.id;

显式内连接

SELECT 字段列表 FROM1 [INNER] JOIN2 ON 连接条件...;
select e.name,d.name from emp e inner join dept d on e.dept_id = d.id ;

外连接

左外连接

SELECT 字段列表 FROM1 LEFT [OUTER] JOIN2 ON 条件...;

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

select e.*,d.name from emp e left outer join dept d on d.id = e.dept_id;

右外连接

SELECT 字段列表 FROM1 RIGHT [OUTER] JOIN2 ON 条件...;

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

select d.*,e.* from emp e right join dept d on d.id = e.dept_id;
select d.*,e.* from dept d left join emp e on d.id = e.dept_id;

自连接

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

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

select e.name '员工',m.name '领导' from emp e join emp m on e.managerid = m.id;
select e.name '员工',m.name '领导' from emp e,emp m where e.managerid = m.id;

select m.name '员工',e.name '领导' from emp m left join emp e on m.managerid = e.id;

联合查询 union,union all

多次查询的结果合并起来,形成一个新的查询结果集

SELECT 字段列表 FROM 表A...
UNION [ALL]
SELECT 字段列表 FROM 表B...;
/*union all直接合并结果,所以有重复数据*/
select * from emp where salary < 5000
union all
select * from emp where age > 50;

/*union会把重复数据删掉*/
select * from emp where salary < 5000
union
select * from emp where age > 50;

对于联合查询的多张表的列数必须保持一致,字段类型也需要保持一致

union all会将全部的数据直接合并在一起,union会对合并之后的数据去重

子查询

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

SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2); 

子查询外部的语句可以是INSERT/UPDATE/DELETE/SELECT中的任何一个
根据子查询结果不同,分为:

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

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

标量子查询

子查询返回的结果是单个值(数字、字符串、日期等),最简单的形式

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

select * from emp where dept_id = (
    select id from dept where name = '销售部'
);

select * from emp where entrydate > (
    select entrydate from emp where name = '方东白'
);

列子查询

子查询返回的结果是一列(可以是多行)

常用的操作符:IN、NOT IN、ANY、SOME、ALL

操作符描述
IN在指定的集合范围之内,多选一
NOT IN不在指定的集合范围之内
ANY子查询返回列表中,有任意一个满足即可
SOME与ANY等同,使用SOME的地方都可以使用ANY
ALL子查询返回列表的所有值都必须满足
select * from emp where dept_id in (
    select id from dept where name = '销售部' or name = '市场部'
);

select * from emp where salary > (
    select max(salary) from emp where dept_id = (
        select id from dept where name = '财务部'
        )
    );

select * from emp where salary > all(
    select salary from emp where dept_id = (
        select id from dept where name = '财务部'
        )
    );

select * from emp where salary > any(
    select salary from emp where dept_id = (
        select id from dept where name = '研发部'
        )
    );

行子查询

子查询返回的结果是一行(可以是多列)

常用的操作符:=、<>、IN、NOT IN

select * from emp where salary = (
    select salary
    from emp
    where name = '张无忌')
and managerid = (
    select managerid
    from emp
    where name = '张无忌');

select * from emp where (salary, managerid) = (
    select salary, managerid from emp where name = '张无忌'
    );

表子查询

子查询返回的结果是多行多列

常用的操作符:IN

/*查询与鹿杖客,宋远桥的职位和薪资相同的员工信息*/
select * from emp where (job, salary) in (select job, salary from emp where name in ('鹿杖客', '宋远桥'));

/*查询入职日期是2006-01-01之后的员工信息,及其部门信息*/
select e.*,dept.* from (select * from emp where entrydate > '2006-01-01') e left join dept on e.dept_id = dept.id;

多表查询案例

create table salgrade(
    grade int,
    losal int,
    hisal int
) comment '薪资等级表';
insert into salgrade values (1,0,3000);
insert into salgrade values (2,3001,5000);
insert into salgrade values (3,5001,8000);
insert into salgrade values (4,8001,10000);
insert into salgrade values (5,10001,15000);
insert into salgrade values (6,15001,20000);
insert into salgrade values (7,20001,25000);
insert into salgrade values (8,25001,30000);

/*查询员工的姓名、年龄、职位、部门信息*/
select e.name,e.age,e.job,d.name from emp e left join dept d on d.id = e.dept_id;
/*查询年龄小于30岁的员工姓名、年龄、职位、部门信息*/
select e.name,e.age,e.job,d.name from emp e left join dept d on d.id = e.dept_id where e.age < 30;
/*查询拥有员工的部门ID、部门名称*/
select distinct d.id,d.name from emp e,dept d where d.id = e.dept_id;
/*查询所有年龄大于40岁的员工,及其归属的部门名称;如果员工没有分配部门,也需要展示出来*/
select e.*,d.name from emp e left join dept d on d.id = e.dept_id where e.age > 40;
/*查询所有员工的工资等级*/
select e.*,s.grade from emp e left join salgrade s on e.salary >= s.losal and e.salary <= s.hisal;
/*查询研发部所有员工的信息及工资等级*/
select y.*, s.grade from (select e.* from emp e,dept d where e.dept_id = d.id and d.name = '研发部') y left join salgrade s on y.salary between s.losal and s.hisal;
select * from emp e,dept d,salgrade s where e.dept_id = d.id and d.name = '研发部' and (e.salary between s.losal and s.hisal);
/*查询研发部员工的平均薪资*/
select avg(e.salary) from emp e left join dept d on d.id = e.dept_id where d.name = '研发部';
/*查询工资比灭绝高的员工信息*/
select * from emp e where e.salary > (
    select salary from emp e where e.name = '灭绝'
    );
/*查询比平均薪资高的员工信息*/
select * from emp e where e.salary > (
    select avg(e.salary) from emp e
    );
/*查询低于本部门平均工资的员工信息*/
select e1.* from emp e1 where e1.salary < (
    select avg(e2.salary) from emp e2 where e1.dept_id = e2.dept_id
    );

select *,(select avg(e2.salary) from emp e2 where e2.dept_id = e1.dept_id) from emp e1 where e1.salary < (
    select avg(e2.salary) from emp e2 where e1.dept_id = e2.dept_id
    );


/*查询所有的部门信息,并统计部门的员工人数*/
select n.name,count(n.id) from (select e.id,d.name from emp e right join dept d on e.dept_id = d.id) n group by n.name ;

select d.id,d.name,(select count(*) from emp e where e.dept_id = d.id) '人数' from dept d;

/*查询所有学生的选课情况,展示出学生名称、学号、课程名称*/
select c.name, c.no, course.name from (select student.name,student.no,student_course.courseid from student left join student_course on student.id = student_course.studentid) c left join course on c.courseid = course.id;

总结

多表关系

一对多:在多的一方设置外键,关联一的一方的主键
多对多:建立中间表,中间表包含两个外键,关联两张表的主键
一对一:用于表结构拆分,在其中任何一方设置外键(UNIQUE),关联另一方的主键

多表查询

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1399279.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis 安装与入门,全文干货

1、简介 Redis 是一个开源的&#xff0c;基于内存的数据存储系统&#xff0c;它可以用作数据库、缓存和消息中间件。它支持多种类型的数据结构&#xff0c;如字符串&#xff08;strings&#xff09;&#xff0c;散列&#xff08;hashes&#xff09;&#xff0c;列表&#xff08…

非科班转码的秋招复盘:地理信息科学GIS专业到后端研发、软件开发

本文介绍地理信息科学&#xff08;GIS&#xff09;专业的2024届应届生&#xff0c;在研三上学期期间&#xff0c;寻找后端研发、软件开发等IT方向工作的非科班转码秋招情况。 首先&#xff0c;这篇文章一开始写于2023年年底&#xff0c;当时为了参加一个征文活动&#xff0c;所…

多维表格产品vika多维表、Flowus、Wolai体验记录

昨天从下午6点肝到凌晨2点多体验低代码平台多维表格产品&#xff0c;体验了3个国内产品&#xff0c;vika多维表、Flowus、Wolai。 具有多维表格新型关系数据库的鼻祖是 Airtable&#xff0c;国内模仿产品有vika多维表、飞书多维表格等。 还有一种类型就是以在国内鼎鼎大名的N…

【Linux】信号量基于环形队列的生产消费模型

信号量 信号量的本质是一个计数器&#xff0c;可以用来衡量临界资源中资源数量多少 信号量的PV操作 P操作&#xff1a;申请信号量称为P操作&#xff0c;P操作的本质就是让计数器减1。 V操作&#xff1a;释放信号量称为V操作&#xff0c;V操作的本质就是让计数器加1 POSIX信号量…

javaWebssh运动会管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh运动会管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,M…

SystemVerilog中数组内置函数sum()的一个注意点

Systemverilog内置了数组求和运算方法(sum())&#xff0c;将数组的所有元素累加起来&#xff0c;返回一个最终值。在使用时要注意数组类型的位宽&#xff0c;通常情况下&#xff0c;如果你将一组单bit的值加起来&#xff0c;Systemverilog会使用足够的精度来确保不丢失任何bit的…

Flink处理函数(2)—— 按键分区处理函数

按键分区处理函数&#xff08;KeyedProcessFunction&#xff09;&#xff1a;先进行分区&#xff0c;然后定义处理操作 1.定时器&#xff08;Timer&#xff09;和定时服务&#xff08;TimerService&#xff09; 定时器&#xff08;timers&#xff09;是处理函数中进行时间相关…

python开发之远程开发工具对比

前言 除了本地开发外&#xff0c;还有一种常见的开发方式就是远程开发&#xff0c;一般情况是一台Windows或mac笔记本作为日常使用的电脑&#xff0c;另有一台linux服务器作为开发服务器。开发服务器的性能往往较强&#xff0c;这样远程开发的方式一方面可以让我们在习惯的系统…

PWM实现呼吸灯

PWM也属于51中的重要章节&#xff0c;本节主要介绍呼吸灯&#xff0c;目的是理解PWM的工作原理&#xff0c;PWM的实验案例重点还得看后续的舵机&#xff08;下一节会讲到&#xff09; 那么何为呼吸灯。呼吸灯的定义是&#xff1a;灯光实现由亮到暗的变化或由暗到亮的逐渐变化。…

一篇文章搞懂什么是测试,测试是干什么的?

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

信号处理专题设计-基于边缘检测的数字图像分类识别

目录 一、实验目的 二、实验要求 三、实验原理 1.卷积神经网络&#xff08;CNN&#xff09;模型 2.边缘检测 3.形态学操作 4.鲁棒性 四、实验过程 1.数据预处理 2. 网络的构建 3.模型的训练 4.边缘检测和形态学操作相关代码 5.模型训练结果 6.关键信息的保存 五、实验测试与评估…

网络安全全栈培训笔记(54-服务攻防-数据库安全RedisHadoopMysqla未授权访问RCE)

第54天 服务攻防-数据库安全&Redis&Hadoop&Mysqla&未授权访问&RCE 知识点&#xff1a; 1、服务攻防数据库类型安全 2、Redis&Hadoop&Mysql安全 3、Mysql-CVE-2012-2122漏洞 4、Hadoop-配置不当未授权三重奏&RCE漏洞 3、Redis-配置不当未授权…

金蝶云星空表单插件获取单据体数据

文章目录 金蝶云星空表单插件获取单据体数据 金蝶云星空表单插件获取单据体数据 使用标识报错 var thisEntry this.View.Model.DataObject["FEntity"] as DynamicObjectCollection;应该使用实体属性 var thisEntry this.View.Model.DataObject["BillEntry&q…

Python连接数据库的梳理

我们通常用的数据库类型主要有关系型数据库&#xff0c;非关系型数据库等&#xff0c;其中关系型数据库主要有Microsoft SQL Server ,MySQL,Oracle&#xff0c;SQLite等&#xff0c;常用的非关系型数据库包括Redis、DynamoDB&#xff0c;MongoDB等 ​​​​​​​ 一 关系型…

Qt文件和目录相关操作

1.相关说明 QCoreApplication类、QFile类、QDir、QTemporaryDir类、QTemporaryFile类、QFileSystemWatcher类的相关函数 2.相关界面 3.相关代码 #include "dialog.h" #include "ui_dialog.h" #include <QFileDialog> #include <QTemporaryDir>…

MySQL综合练习题

一、创建表的素材 CREATE TABLE dept ( deptno INT(2) NOT NULL COMMENT 部门编号, dname VARCHAR (15) COMMENT 部门名称, loc VARCHAR (20) COMMENT 地理位置 ); -- 添加主键 ALTER TABLE dept ADD PRIMARY KEY (deptno); -- 添加数据 INSERT INTO dept (deptno…

nuclei安装;linux上 以及使用教程

kali安装go环境_go1.17 kali安装-CSDN博客Ubuntu完美解决Github网站打不开问题 - 一抹烟霞 - 博客园 (cnblogs.com) All releases - The Go Programming Language 然但是上面两个我似乎都没用到网上的教程 也不适用 一个网不好 一个apt没找到包 然后我先试试了版本 结果 我的…

组件通信方式

组件通信 父子组件通信 单向数据流 属性传递props&#xff08;还有插槽&#xff0c;$attrs非属性&#xff09;/$emit&#xff0c;发布订阅模式 方法也可以作为属性 父子组件渲染生命周期&#xff1a; 获取组件实例。$children、ref&$refs/$parent 祖先和后代 组件和后代通信…

python之粘包/粘包的解决方案

python之粘包/粘包的解决方案 什么是粘包 粘包就是在数据传输过程中有多个数据包被粘连在一起被发送或接受 服务端&#xff1a; import socket import struct# 创建Socket Socket socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 绑定服务器和端口号 servers_addr (…

java打包及上传到私服务

一、准备Maven私服Nexus 添加saas.maven 仓库地址&#xff1a;http://192.168.31.109:8081/repository/saas.maven 二、新建SpringBoot项目com.saas.pdf 添加类&#xff1a;PdfUtil.java package com.saas.pdf;public class PdfUtil {public static void Save(String fileP…