【MySQL】联合查询

news2025/1/17 13:53:50

目录

1、前言

2、联合查询

3、内连接和外连接

4、案例演示

4.1 查询篮球哥每科的成绩

4.2 查询所有同学的总成绩及邮箱

5、自连接

5.1 显示所有计算机原理成绩比java成绩高的同学

6、子查询

6.1 查询出篮球哥的同班同学

6.2 多行子查询

7、合并查询


1、前言

在实际开发中,往往数据是来自不同的表,所以需要多表联合查询,多表查询是对多张表的数据取笛卡尔积。

这里就需要简单了解下笛卡尔积的概念了:

集合A {a1,a2,a3} 集合B {b1,b2},他们的 笛卡尔积 是 A*B = { (a1,b1), (a1,b2), (a2,b1), (a2,b2), (a3,b1), (a3,b2)}任意两个元素结合在一起。

如上图所示,笛卡尔积就是把这两个表放到一起进行计算,分别取出第一张表的每一行,和第二张表的每一行配对,得到一个新的记录。


2、联合查询

有了上述笛卡尔积的认识,我们就来使用下联合查询,首先准备 student,class 这两张表,并且增加相关的数据:

create table student (
    id int primary key,
    name varchar(20),
    classId int
);

create table class (
    classId int primary key,
    name varchar(20)
);

insert into student value
    (23001, '张三', 1),
    (23002, '李四', 2),
    (23003, '王五', 1),
    (23004, '赵六', 3),
    (23005, '孙七', 3);

insert into class value
    (1, 'java1班'),
    (2, 'java2班'),
    (3, 'java3班');

 

有了上述的数据后,我们就来进行简单的联合查询(通过 student class 表 查询出每个学生对应的班级):

这里我们发现,同时查询两张表,进行了笛卡尔积,跟我们上述画的图是一样的效果,但是这里我们发现有很多无效的元素,按道理来说,张三的 classId 为 1,对应 class 表应该是 java1 班的,所以这里的数据是存在很多无效数据的,此时我们就可以使用 where 条件来进行筛选:

有了筛选条件后,显然发现就没有了那些无效的数据了,此时我们再次省略我们不想要的列,只保留学生姓名和班级名称就好了:

这样一来得到的结果就是我们想要的结果了。

上述可能有一个点之前没有说过,比如 student.classId 和 class.classId,这里为什么要加 表名. 前缀呢?由于我们进行的是多表查询,势必可能会出现不同表中存在相同的列名,这里我们就需要告诉 MySQL 是那个表中的列。如果不加表名,这时就区分不了是哪个表的列了,随之就会报错!

上述是最基础的多表查询,后面我们就来用案例来学习更复杂的多表查询。


3、内连接和外连接

在大多数情况下,都是没有啥区别的,比如要连接的两个表中,里面的数据都是一一对应的,这个时候就没有区别,如果不是一一对应,内连接和外连接就有区别了。

这里我们有这样的两张表,通过看数据可以发现,student表中张三在score表中是没有成绩的,而score表中studentId为4是没有对应学生的。我们就用上述两张表进行联合查询演示下外连接和内连接的区别:

select * from student, score where student.id = score.studentId;
select * from student join score on student.id = score.studentId;
-- 这两种的写法都是一样的效果
+------+--------+-----------+-------+
| id   | name   | studentId | java  |
+------+--------+-----------+-------+
|    1 | 张三   |         1 | 89.00 |
|    2 | 李四   |         2 | 92.00 |
+------+--------+-----------+-------+

上述的写法都属于内连接,此处查询结果中,最终剩下的就是两个表里都有的数据,都能关联上的数据,如果使用外连接,那么结果就不相同了。

● 左外连接: 

select * from student left join score on student.id = score.studentId;

● 右外连接:

select * from student right join score on student.id = score.studentId;

我们对比这两种两种连接方式,来观察他们的区别:

  • 左外连接会把左表的结果都列出来,哪怕右表中没有相应的数据,就使用 NULL 来填充
  • 右外连接会把右表的结果都列出来,哪怕左表中没有相应的数据,就使用 NULL 来填充 

后续为了演示更复杂的多表查询,以及结合实际的情况,这里我们需要重新构建四张表: 

create table classes (
        id int primary key auto_increment, 
        name varchar(20), 
        synopsis varchar(100)
        );

create table student (
        id int primary key, 
        name varchar(20), 
        qq_mail varchar(20) ,
        classes_id int
        );

create table course (
        id int primary key auto_increment, 
        name varchar(20)
        );

create table score (
        score decimal(3, 1), 
        student_id int, 
        course_id int
        );

由于插入数据部分代码太多,不方便放入文章里,大家可以自行录入,也可以去博主的主页去下载现成的 SQL 文件哦。


4、案例演示

4.1 查询篮球哥每科的成绩

此时要注意篮球哥的信息在 student 表中,而成绩在 score 表里,课程名又在 course 表中,而 score 表中包含了 sutdent_id 以及 course_id:

select student.name as '姓名', course.name as '课程名', score.score as '分数' 
from student, score, course 
where student.id = score.student_id and 
      score.course_id = course.id and 
      student.name = '篮球哥';

这里为了大家看的方便,就进行了换行,最终我们只需要显示三个字段,数据来源于 student,score,course 表,接下来就是 where 条件部分了,相信也是清晰明了的。

4.2 查询所有同学的总成绩及邮箱

此时要用到 student,score 这两个表,并且还要使用聚合函数进行求每个同学的总分,也就是要对每个同学的 id 进行分组后,成绩求和。

select student.name, sum(score) as '总分', student.qq_mail
from student, score 
where student.id = score.student_id 
group by student.id;
-- 成绩表对学生表是多对1关系,查询总成绩是根据成绩表的同学id来进行分组的

这里交大家一个简单的方法读 sql 语句,select 后面最终显示的列,from 后面是数据来源的表,where 是进行筛选的条件,group by 是按照某个字段进行分组。这样一来就简洁明了了。


5、自连接

自连接就是自己跟自己笛卡尔积,这不是一个通用的解决方案,而是特殊问题的特殊处理方法,自连接的效果就是把 行 转换成 列,这里我们举个例子:

5.1 显示所有计算机原理成绩比java成绩高的同学

select * from score, score;
-- ERROR 1066 (42000): Not unique table/alias: 'score'

这里发现直接自己跟自己笛卡尔积会报错,说名字重复了,不是唯一的,可以采用取别名的方式来解决这个错误:

select * from score as s1, score as s2;

首先我们要明确这 java 和 计算机原理 的课程 ID 是多少:

select * from course;
+----+--------------------+
| id | name               |
+----+--------------------+
|  1 | Java               |
|  2 | 中国传统文化       |
|  3 | 计算机原理         |
|  4 | 语文               |
|  5 | 高阶数学           |
|  6 | 英文               |
+----+--------------------+
-- 6 rows in set (0.00 sec)

得到了 java 和 计算机原理 的 id 之后,对 score 表自身进行笛卡尔积,就可以指定 s1.class_id = 1 and s2.class_id = 3 这样的条件,也就是将一行中 s1 表显示 java, s2 表显示计算机原理:

select * from score as s1, score as s2 where s1.course_id = 1 and s2.course_id = 3;

此查询结果还存在无效的数据,比如 s1.student_id 与 s2.student_id 应该是一样的, 因为我们查询的是谁的计算机原理比Java成绩高,所以我们还要加上一个条件:

select * from score as s1, score as s2 
where s1.course_id = 1 
and s2.course_id = 3 
and s1.student_id = s2.student_id;

现在这个结果是满足 id 相等,同时满足了要比较的科目,现在就差一个条件了!就是 s1.score < s2.score 这就表示查询的是 java 成绩小于 计算机原理的同学:

select * from score as s1, score as s2 
where s1.course_id = 1 
and s2.course_id = 3 
and s1.student_id = s2.student_id 
and s1.score < s2.score;

最后我们对这个结果保留想要的字段,并且增加 student.name 这个字段,注意增加 student.name 表示要多一个student 表一起进行笛卡尔积,所以我们还要加一个条件 student.id = s1.student_id,这样才是最终完整的结果:

 select student.name, s1.score as Java, s2.score as 计算机原理 
 from student, score as s1, score as s2
 where s1.student_id = s2.student_id 
 and s1.course_id = 1 
 and s2.course_id = 3 
 and s1.score < s2.score 
 and student.id = s1.student_id;

以上就完整的查询出了 计算机原理成绩大于Java成绩的同学了! 这个过程看似复杂,但不要着急,静下心来一步步分析,阅读 SQL,相信你能理解的!


6、子查询

子查询本质就是套娃,实际开发中,慎重使用,子查询可能会构造出非常复杂,非常不好理解的 SQL,对于代码的可读性就大大降低了,对于 SQL 的执行效率,也有可能是毁灭性的打击!

6.1 查询出篮球哥的同班同学

正常情况下,先查询出篮球哥的班级id,然后条件设置为 claases_id 跟 篮球哥的班级id 相同即可,并排掉篮球哥:

select classes_id from student where name = '篮球哥';
-- 1
select * from student where classes_id = 1 and name != '篮球哥';

这样就能求出篮球哥的同班同学,但是子查询是如何写的呢?

select * from student where classes_id = (select classes_id from student where name = '篮球哥') and name != '篮球哥';

子查询的写法其实就是套娃!把一个查询的结果,作为另一个查询的一部分条件(此处作为另一个一部分查询条件的查询结果只能返回一条数据) 。

6.2 多行子查询

● 查询语文或英文课程的成绩信息

正常情况下,我们需要先查询出语文和英文的课程id,然后去成绩表中查询对应课程id 的成绩:

select id from course where name = '语文' or name = '英文';
-- 4 6
select * from score where course_id = 4 or course_id = 6;

如果要用多行子查询就需要利用 in 关键字:

select * from score where course_id in (select id from course where name = '语文' or name = '英文');

如果查询是排除语文英文信息呢?就使用 not in 就行,可以把 in 理解成再这个范围内,整体查询结果必须满足 in 后面子查询的结果范围。

这里的套娃是无穷无尽的,一般不建议这样做,实际上更推荐是直接多步完成查询就好,没必要强行合成一个!


7、合并查询

合并查询就比较简单了,本质上就是把两个查询的结果集合并成一个。

● 查询课程id小于3,或者课程名为英文的课程

select * from course where id < 3 union select * from course where name = '英文';

这里可能有小伙伴就很奇怪,这中间直接来个 or 不就行了吗?是的!

注意:这里的 union 是可以来自于不同的表,只要查询的结果的列匹配即可,而 or 只能是同一表。  

除了 union 还有一个 union all,他们区别不大,union 是会进行去重(重复的行只会保留一份),而 union all 是不会去重的!


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

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

相关文章

macOS Monterey 12.6.5 (21G531) 正式版发布,ISO、IPSW、PKG 下载

本站下载的 macOS 软件包&#xff0c;既可以拖拽到 Applications&#xff08;应用程序&#xff09;下直接安装&#xff0c;也可以制作启动 U 盘安装&#xff0c;或者在虚拟机中启动安装。另外也支持在 Windows 和 Linux 中创建可引导介质。 2023 年 4 月 10 日&#xff08;北京…

如何使用Midjourney辅助建筑平面设计和室内设计,常用的建筑平面效果图提示和使用效果展示(内附Midjourney提示词网站)

文章目录一、室内建筑平面设计1.AutoCAD图纸&#xff08;别墅图为例&#xff09;2.平面效果图3.三维平面透视图二、建筑室内设计1.现代简约2.波西米亚风格3.工业风格4.沿海风格5.法国风格6.现代风格7.提示增加颜色倾向8.提示中增加设计师9.其它一些尝试三、好用的Midjourney提示…

unity 全局光照

全局光照由两部分组成&#xff1a;直接光照和间接光照。 直接光照由直接光照射到物体上以后直接弹射到人眼接收到的光照。 间接光照为直接光照照射到物体上又弹射到其它物体上面以后多次弹射才被人眼接收的光照&#xff08;两次及以上的光照统称为间接光照&#xff09; 材质光…

消息队列RocketMQ、Kafka小计

1、消息队列模型 点对点模式 &#xff08;一对一&#xff0c;消费者主动拉取数据&#xff0c;消息收到后消息清除&#xff09;点对点模型通常是一个基于拉取或者轮询的消息传送模型&#xff0c;这种模型从队列中请求信息&#xff0c;而不是将消息推送到客户端。这个模型的特点是…

Observability: Elastic RUM (真实用户监控)演示

在之前的文章 “Elastic RUM&#xff08;真实用户监测&#xff09;浅谈”&#xff0c;我们详细描述了 Elastic RUM &#xff08;Real User Monitor&#xff09;。在今天的文章中&#xff0c;我将详细一步一步地对该文章进行演示以便大家也能和我一样进行展示。在今天的展示中&a…

Docker6种网络配置详解,网络模式应该这么选

文章目录一、Bridge网络模式二、Host网络模式三、Overlay网络模式四、None网络模式五、Macvlan网络模式六、Ipvlan网络模式七、网络模式选择在Docker中&#xff0c;网络配置是一个重要的主题&#xff0c;因为容器需要与其他容器或外部网络进行通信。Docker提供了多种网络模式和…

GPT-4 和ChatGPT API的定价分析

OpenAI发布了他们的ChatGPT新机器学习模型GPT-4。GPT-4是GPT-3的一大进步&#xff0c;GPT-3是当前ChatGPT免费版本(GPT 3.5 Turbo)所运行的模型的基础&#xff0c;今天我们也来凑个热点&#xff0c;研究一下它们的定价 GPT-4新的功能 GPT-4可以在对话中使用图像&#xff0c;并…

2023年美赛春季赛 赛题浅析

由于今年各种各样的原因&#xff0c;导致美赛头一次&#xff0c;据说也将是最后一次&#xff0c;临时调整&#xff0c;加设春季赛。这对于急需建模奖项的大家来说是一个很好的机会。无论怎样的原因&#xff0c;今年美赛我们可能有所遗憾。但&#xff0c;春季赛也许就是弥补遗憾…

在不丢失数据的情况下解锁锁定的 Android 手机的 4 种方法

尽管您可以使用指纹解锁手机&#xff0c;但大多数智能手机都需要 PIN 码、图案或字母数字代码作为主密码。如果您有一段时间没有输入手机密码&#xff0c;很容易忘记。正是由于这个原因&#xff0c;即使您打开了指纹解锁&#xff0c;大多数智能手机也会让您每天至少输入一次 PI…

Linux之磁盘分区、挂载

文章目录一、Linux分区●原理介绍●硬盘说明查看所有设备挂载情况挂载的经典案例二、磁盘情况查询基本语法应用实例磁盘情况-工作实用指令一、Linux分区 ●原理介绍 Linux来说无论有几个分区&#xff0c;分给哪一目录使用&#xff0c;它归根结底就只有一个根目录&#xff0c;…

【软考五】数据库(做题)

该文章不适合学习数据库&#xff0c;适合考证&#xff0c;遇到实际问题的&#xff0c;不要在这儿浪费时间。切记切记 软考之数据库一、概念数据模型&#xff08;下午题常考&#xff09;二、结构数据模型关系模型1、关系模型中基本术语2、关系模型中的关系完整性约束3、关系代数…

SQL Server 数据查询

文章目录前言首先在SQL Server 2008 中新建一个数据库chaxun.在库中建三个表,结构如下表所示,并且录入数据.1.2.(1)在KC表中查询学分低于三分的课程信息&#xff0c;并按课程号升序排列(2)在XS_KC表中按学号分组汇总学生的平均分&#xff0c;并按平均分的降序排列(3)在XS_KC表中…

「文心一言」内测详细使用体验

★观前提示&#xff1a;以下内容仅为内测测试内容&#xff0c;不代表未来正式版如何&#xff0c;或许你认为它与chatgpt仍有不小的差距&#xff0c;或许你认为它目前做的已经不错了&#xff0c;都可以&#xff0c;但是咱们测试体验&#xff0c;只讲述体验&#xff0c;本篇文章不…

【数字图像处理】直方图均衡化

文章目录1. 算法原理2. 算法缺陷及改进2.1 缺陷2.2 改进3. 实现3.1 调包侠版本3.2 自由发挥版本1. 算法原理 直方图均衡化是一种常见的图像增强方法&#xff0c;可以增强图像的对比度。其数学原理如下&#xff1a; 首先&#xff0c;我们需要了解直方图的概念。直方图是对图像…

Bezier Curve 贝塞尔曲线 - 在Unity中实现路径编辑

文章目录简介一阶贝塞尔曲线二阶贝塞尔曲线三阶贝塞尔曲线图形理解 Bezier Curve一阶贝塞尔曲线二阶贝塞尔曲线三阶贝塞尔曲线应用Bezier CurveSimpleBezierCurvePathSimpleBezierCurvePathAlonger简介 贝塞尔曲线&#xff08;Bezier Curve&#xff09;&#xff0c;又称贝兹曲…

人工智能概述

一、人工智能发展必备三要素 算法 数据 算力 CPU、GPU、TPU 计算力之CPU、GPU对比&#xff1a; CPU主要适合I\O密集型任务GPU主要适合计算密集型任务 什么样的程序适合在GPU上运行&#xff1f; 计算密集型的程序 所谓计算密集型(Compute-intensive)的程序&#xff0c;就是…

【K8S系列】深入解析无状态服务

目录 序言 1. 无服务介绍 1.1 优点 1.2 使用场景 1.3 资源类型 1.4 总结 2 使用介绍 2.1 Deployment 使用场景&#xff1a; 2.2 ReplicaSet 使用场景 2.3 pod Pod 资源定义示例 2.4 service 创建一个Deployment&#xff1a; 创建一个Service&#xff1a; 总结…

前置知识——Linux网络虚拟化

Linux网络虚拟化 信息是如何通过网络传输被另一个程序接收到的&#xff1f; 我们讨论的虚拟化网络是狭义的&#xff0c;它指容器间网络。 好了&#xff0c;下面我们就从 Linux 下网络通信的协议栈模型&#xff0c;以及程序如何干涉在协议栈中流动的信息来开始了解吧。 Linux…

基于飞桨实现的特定领域知识图谱融合方案:ERNIE-Gram文本匹配算法

文本匹配任务在自然语言处理领域中是非常重要的基础任务&#xff0c;一般用于研究两段文本之间的关系。文本匹配任务存在很多应用场景&#xff0c;如信息检索、问答系统、智能对话、文本鉴别、智能推荐、文本数据去重、文本相似度计算、自然语言推理、问答系统、信息检索等&…

【MySQL】了解MySQL的Explain,读这一篇够了( ̄∇ ̄)/

目录 ID select_type 查询类型 table 表名 type 关联类型/访问类型 possible_keys MySQL觉得可能要用到的索引 key 实际用到的索引 key_len 用到的索引的长度&#xff08;比如可用于判断使用了联合索引中的哪几个&#xff09; ref 表查找值所用的列&#xff08;表名.字…