MySQL数据库,联合查询

news2024/11/14 14:54:21

目录

1. 联合查询

1.1 内查询

1.2 外查询

1.3 自连接

1.4 子查询

1.5 合并查询


1. 联合查询

联合查询,简单的来讲就是多个表联合起来进行查询。这样的查询在我们实际的开发中会用到很多,因此会用笛卡尔积的概念。

啥是笛卡尔积?两张表经过笛卡尔积后得到的新表的列数是两表列数之和,行数是两表行数之积。

我们可以看到下图中两表形成一个笛卡尔积后,把这两张表组成情况的所有的可能性都罗列出来了。因此会造成出现很多无用数据,这就是笛卡尔积的一个简单理解。因此,我们在查询两个表时得使用一些方法来避免类似于笛卡尔积这种情况的出现,这些方法的总称就是联合查询。

当然,上图两表中的数据没有任何关联,在此解释一下。 


在我们进入联合查询的各个知识点讲解之前,我们先来创建几张表。下方的所有联合查询都是通过这几张表来进行演示的。

首先创建一个名为student的表作为学生表:

//创建student表
mysql> create table student(
    -> id int primary key auto_increment,
    -> sn varchar(20),
    -> name varchar(20),
    -> e_mail varchar(20),
    -> classes_id int
    -> );
Query OK, 0 rows affected (0.02 sec)

//往student表中插入数据
mysql> insert into student(id,sn,name,e_mail,classes_id) values
    -> (1,23001,'阿三','asan@qq.com',1),
    -> (2,23005,'李四','lisi@qq.com',2),
    -> (3,23011,'王五',null,2),
    -> (4,23002,'赵六','zhaoliu@qq.com',2),
    -> (5,23015,'老八',null,1);
Query OK, 5 rows affected (0.00 sec)
Records: 5  Duplicates: 0  Warnings: 0

student表的内容为: 


创建一个名为classes的表作为成绩表:

//创建表classes
mysql> create table classes(
    -> id int primary key auto_increment,
    -> name varchar(20),
    -> descr varchar(100)
    -> );
Query OK, 0 rows affected (0.02 sec)

//往classes中插入数据
mysql> insert into classes(id,name,descr) values
    -> (1,'计算机专业','学习了C、Java、数据结构与算法'),
    -> (2,'医护专业','学习了康复相关知识');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

classe表的内容为: 


创建一个名为course的表作为课程表:

//创建course表
mysql> create table course(
    -> id int primary key auto_increment,
    -> name varchar(20)
    -> );
Query OK, 0 rows affected (0.02 sec)

//往course表中插入数据
mysql> insert into course(id,name) values
    -> (1,'Java'),
    -> (2,'英语'),
    -> (3,'数学'),
    -> (4,'中华传统文化'),
    -> (5,'摆烂');
Query OK, 5 rows affected (0.00 sec)
Records: 5  Duplicates: 0  Warnings: 0

course表的内容为: 


创建一个名为score的表作为成绩表:

//创建一个score表
mysql> create table score(
    -> score int,
    -> student_id int,
    -> course_id int
    -> );
Query OK, 0 rows affected (0.02 sec)

//插入相应的数据
mysql> insert into score(score,student_id,course_id) values
    -> (80,1,1),
    -> (60,1,2),
    -> (70,1,5),
    -> (66,2,4),
    -> (88,2,1),
    -> (99,3,5),
    -> (20,3,1),
    -> (78,4,4),
    -> (66,4,2),
    -> (89,4,1),
    -> (99,5,2),
    -> (77,5,3),
    -> (76,5,4);
Query OK, 13 rows affected (0.01 sec)
Records: 13  Duplicates: 0  Warnings: 0

score表中的内容为: 

通过上面创建的四张表,我们可以知道这几张表之间的联系。

当然不止上图三表中之间有联系,student表中的classes_id与classes表中的id也是有关联。因此,这四张表之间都是相互关联的,那么我们就可以通过联合查询来操作相应的数据。


1.1 内查询

内查询是表与表之间通过一些内部相同数据的关联进行查询,因此当我们把需要查询的表进行笛卡尔积后,可以根据表之间内部相同的字段来作为连接条件从而筛选到要想的数据。内连接语法为:

  • select 字段 from 表1 别名1 join 表2 别名2 on 连接条件 and 其他连接条件;
  • select 字段 from 表1 别名1,表2 别名2 where 连接条件 and 其他连接条件;

如果查我们要找名为阿三同学的成绩,这时就会使用到两张表:student、score。这两张表进行笛卡尔积后数据非常的冗杂:

mysql> select * from student,score;

足足有65行数据,我们要查找阿三的同学的成绩会使用到两个条件:第一个条件为name='阿三',第二个条件就是student.id = score.student_id。这样就能避免出现其他无效的数据。

那么在对两张表进行笛卡尔积过后,我们有两种方式来进行查询阿三同学的成绩,第一种使用join on的方式进行查询: 

mysql> select name,score from student join score on name='阿三' and student.id=score.student_id;
+------+-------+
| name | score |
+------+-------+
| 阿三 |    80 |
| 阿三 |    60 |
| 阿三 |    70 |
+------+-------+
3 rows in set (0.00 sec)

第二种方式,使用where的方式进行查询: 

mysql> select name,score from student,score where name='阿三' and student.id = score.student_id;
+------+-------+
| name | score |
+------+-------+
| 阿三 |    80 |
| 阿三 |    60 |
| 阿三 |    70 |
+------+-------+
3 rows in set (0.00 sec)

通过上方代码之间的比较我们不难发现,join on和where这两种方式都能达到我们的目的,因此只要能掌握其中一种方式就能达到内查询的效果。注意,上述代码中我们可以通过.号来引用相关字段。当两张表中有相同字段name时我们可以通过表1.name来访问到表1中的name,通过表2.name来访问到表2中的name。 


经过上方简单的程序相信大家已经对内查询有了初步的了解,下面我们来升级难度:查询所有同学的总成绩,及同学的个人信息。

首先我们要知道这些数据的来源于student和score这两张表,并且我们要得到student中的所有学生信息score中的成绩总和,以及条件为student中的id等于score中的student_id。这样我们就可以写出以下代码:

mysql> select stu.id,stu.name,stu.e_mail,stu.classes_id,sum(sco.score)
    -> from student stu join score sco on stu.id=sco.student_id
    -> group by sco.student_id;
+----+------+----------------+------------+----------------+
| id | name | e_mail         | classes_id | sum(sco.score) |
+----+------+----------------+------------+----------------+
|  1 | 阿三 | asan@qq.com    |          1 |            210 |
|  2 | 李四 | lisi@qq.com    |          2 |            154 |
|  3 | 王五 | NULL           |          2 |            119 |
|  4 | 赵六 | zhaoliu@qq.com |          2 |            233 |
|  5 | 老八 | NULL           |          1 |            252 |
+----+------+----------------+------------+----------------+
5 rows in set (0.00 sec)

在上述代码中stu是student的别名,sco是score的别名。因此我们from前就可以使用这两个别名进行.操作来获取字段,但这种代码的可读性并不太高,建议使用原表名来获取字段而不是使用别名来获取字段。如将上方代码修改为使用表名来.引用字段:

select student.id,student.name,student.e_mail,student.classes_id,sum(score.score)

from student join score on student.id = score.student_id

group by score.student_id;

1.2 外查询

那么在上述内查询的使用时,其实都是表之间的“内连接”,在MySQL中还有一种联合查询叫作“外连接”,也就是现在我们要学的外查询。

何为外查询,如在两张表中有一部分数据是有关联的另一部分数据是没有关联的,我们可以通过外查询把表1中不存在的数据或表2中不存的的数据通过外查询显示出来。有些抽象,下面我就用实例来讲解。外查询分为左外连接与右外连接,语法为:

  • select 字段 from 表1 left join 表2 on 连接条件; --左外连接,表1完全显示
  • select 字段 from 表1 right join 表2 on 连接条件; --右外连接,表2完全显示

在mytest数据库中创建两张表,student学生表和score课程表:

//创建名为mytest的数据库
mysql> create database mytest charset utf8;
Query OK, 1 row affected (0.00 sec)

//使用该数据库
mysql> use mytest;
Database changed

//创建学生表
mysql> create table student(
    -> id int,
    -> name varchar(10),
    -> sex varchar(10)
    -> );
Query OK, 0 rows affected (0.02 sec)
//插入对应数据
mysql> insert into student values
    -> (101,'张三','男'),
    -> (102,'李四','女'),
    -> (103,'王五','男');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

//创建成绩表
mysql> create table score(
    -> student_id int,
    -> score int
    -> );
Query OK, 0 rows affected (0.02 sec)
//插入相应数据
mysql> insert into score values (101,99),(102,89);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

这两张表的内容为:

有一需求:查找这两张表的id,name,score这三条信息,要求为有效信息。当我们通过内连接,左外连接以及右外连接进行查询就会发现不同之处。

内连接查询:

mysql> select student.id,student.name,score.score from student join score on student.id = score.student_id;
+------+------+-------+
| id   | name | score |
+------+------+-------+
|  101 | 张三 |    99 |
|  102 | 李四 |    89 |
+------+------+-------+
2 rows in set (0.00 sec)

我们发现使用内连接进行查询得到的结果是正确的,关联性比较强。我们再来看左连接查询:

mysql> select student.id,student.name,score.score from student left join score on student.id = score.student_id;
+------+------+-------+
| id   | name | score |
+------+------+-------+
|  101 | 张三 |    99 |
|  102 | 李四 |    89 |
|  103 | 王五 |  NULL |
+------+------+-------+
3 rows in set (0.00 sec)

通过上述代码我们发现,查询的结果并不有效。把score表中不存在的字段给查询出来了,我们可以把student和score这两张表看作两个数学里面的集合,这样就不难理解:

当我们的连接条件为student.id=score.student_id时,我们通过左外连接时强制要得到左表也就是student表中的信息,那么student表中id为103的行中没有score值,此时就会显示null。右连接则不会出现这种情况:

mysql> select id,name,score from student right join score on student.id = score.student_id;
+------+------+-------+
| id   | name | score |
+------+------+-------+
|  101 | 张三 |    99 |
|  102 | 李四 |    89 |
+------+------+-------+
2 rows in set (0.00 sec)

因为右连接根据右表也就是score表进行查询,score表中关于id的信息有101和102因此通过条件为student.id=score.student_id进行查询后得到的结果也是存在的。


1.3 自连接

自连接是一种特殊情况下才使用的查询方式,它是一种取巧的查询方式,何为取巧?我们通过上方的内连接与外连接的学习知道了这两种都是表与表之间进行连接的,而自连接它是表自己和自己进行连接的,因此我认为它是取巧的一种方式。

如使用自连接查找Java成绩要大于摆烂成绩:

因为是自连接所以只能用到score这一张表。此外,我们需要知道Java成绩的课程id和摆烂成绩的课程id这样才能去比较它们的成绩。

 因此,我们可以写出以下代码:

mysql> select
    -> s1.*
    -> from
    -> score s1,
    -> score s2
    -> where
    -> s1.student_id = s2.student_id
    -> and s1.score<s2.score
    -> and s1.course_id = 1
    -> and s2.course_id = 5;
+-------+------------+-----------+
| score | student_id | course_id |
+-------+------------+-----------+
|    20 |          3 |         1 |
+-------+------------+-----------+
1 row in set (0.00 sec)

当然,我们也可以使用join on方式来实现:

mysql> select
    -> s1.*
    -> from
    -> score s1
    -> join
    -> score s2
    -> on
    -> s1.student_id = s2.student_id
    -> and s1.score<s2.score
    -> and s1.course_id = 1
    -> and s2.course_id = 5;
+-------+------------+-----------+
| score | student_id | course_id |
+-------+------------+-----------+
|    20 |          3 |         1 |
+-------+------------+-----------+
1 row in set (0.00 sec)

我们可以看到,Java小于摆烂的成绩只有一条。


1.4 子查询

子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询。什么意思呢,就是在查询一些数据的时候使用另一条select语句作为查询条件,从而达到特定的查询效果

如查找老八及与同班级的学生,首先我们要查找student表中的所有信息,在where条件后面再加上条件。这个条件为classes_id=老八的classes_id,注意老八的classes_id可以使用另一条select语句来查询。因此可以写出以下代码:

mysql> select * from student where classes_id=(select classes_id from student where name = '老八');
+----+-------+------+-------------+------------+
| id | sn    | name | e_mail      | classes_id |
+----+-------+------+-------------+------------+
|  1 | 23001 | 阿三 | asan@qq.com |          1 |
|  5 | 23015 | 老八 | NULL        |          1 |
+----+-------+------+-------------+------------+
2 rows in set (0.01 sec)

使用in关键字也能做到嵌套查询这种效果,如查询与李四同班的同学信息:

mysql> select * from student where classes_id in (select classes_id from student where name = '李四');
+----+-------+------+----------------+------------+
| id | sn    | name | e_mail         | classes_id |
+----+-------+------+----------------+------------+
|  2 | 23005 | 李四 | lisi@qq.com    |          2 |
|  3 | 23011 | 王五 | NULL           |          2 |
|  4 | 23002 | 赵六 | zhaoliu@qq.com |          2 |
+----+-------+------+----------------+------------+
3 rows in set (0.00 sec)

注意,in关键可以表示一个范围,只要是满足in()里面的内容就可以被查询出来,查询一个字段满足5,6,7这三个条件。则字段 in(5,6,7)即可。


1.5 合并查询

在实际应用中,为了合并多个select的执行结果,可以使用集合操作符 union,union all。使用union和union all时,前后查询的结果集中,字段需要一致。

union操作符:

查找id<3并且name=摆烂的课程,我们会用到course表,使用两个select语句进行查询我们会使用union这个操作符进行连接,因此有以下代码:

mysql> select * from course where id < 3 union select * from course where name = '摆烂';
+----+------+
| id | name |
+----+------+
|  1 | Java |
|  2 | 英语 |
|  5 | 摆烂 |
+----+------+
3 rows in set (0.00 sec)

或者我们使用or来实现:

mysql> select * from course where id < 3 or name = '摆烂';

注意,使用union操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行。


union all操作符:

该操作符用于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行。如查询id<3或者name='Java'的课程:

mysql> select * from course where id < 3 union all select * from course where name = 'Java';
+----+------+
| id | name |
+----+------+
|  1 | Java |
|  2 | 英语 |
|  1 | Java |
+----+------+
3 rows in set (0.00 sec)

我们可以看到,重复被查询的Java字段出现了两次。


今天这篇博文内容比较丰富,大家下来了可以自行测试每个查询所实现的效果,只有自己尝试了并且实现了一些效果,这样才会更好的掌握这些知识点。

本期博文到这里就结束,感谢各位的阅读。

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

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

相关文章

深度学习 -- 张量操作与线性回归 张量的数学运算以及用张量构建线性回归模型

前言 这篇博客继承前篇博客的内容&#xff0c;将对张量的操作进行阐述&#xff0c;同时在理解张量的一些数学的基础上&#xff0c;配合机器学习的理论&#xff0c;在pytorch环境中进行一元线性回归模型的构建。 张量的拼接与切分 torch.cat() 功能&#xff1a;将张量按维度d…

Node.js四:包管理工具

1.介绍 2.npm安装 3.npm基本使用 属性翻译 4.搜索下载安装包 npm搜索网站&#xff1a; npm 5.生产环境与开发环境 开发环境 是程序员 专门用来写代码 的环境&#xff0c;一般是指程序员的电脑&#xff0c;开发环境的项目一般 只能程序员自己访问 生产环境 是项目 代码正式运行 …

海光信息业绩高歌猛进,但其作为国产CPU龙头的“地基”并不牢固

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 在“芯片寒冬”的大背景下&#xff0c;2022年全球头部芯片半导体公司纷纷下调业绩预期&#xff0c;英特尔、英伟达、美光等无一幸免。但是随着AIGC异军突起&#xff0c;仿佛寒冬中的一股暖流&#xff0c;催生着半导体市场行…

第四章 面向对象(OOP)

目录 一、编程思想 1.1. 面向对象 1.2. 面向过程 1.3.举例说明&#xff08;把大象装进冰箱&#xff09; 1.4.二者的联系与区别 1.5.面向对象的三个阶段 1.6.什么是类&#xff0c;什么是实例&#xff0c;二者的联系 二、面向对象三大特征 2.1 封装 2.2 继承 2.3 多态…

go-zero入门

文章目录 简介框架设计环境准备go安装Go Module设置goctl安装安装(mac\&linux)安装(windows) protoc & protoc-gen-go安装 goctl 各层代码生成一览goctl 生成REST和RPC微服务生成数据模型层Model生成API服务目录结构开发者需要做的修改配置文件修改上下文依赖修改业务逻…

CMake基本使用

重要指令 cmake_minimum_required:指定CMake最小版本要求 project&#xff1a;定义工程名称&#xff0c;并可指定语言 set&#xff1a;显示的定义变量 include_directories&#xff1a;向工程添加多个特定头文件搜素路径 link_directories&#xff1a;向工程添加多个特定库文件…

Spring lettuce读写分离

Redis 的 Sentinel 模式默认配置下 Redis 的客户端只对 Master 读写&#xff0c;另外2个Slave闲置。若主从节点在不同机房&#xff0c;在读取时会有跨机房的网络时延&#xff0c;并且比同机房访问更容易发生网络丢包。故在一些场景可以考虑将跨机房的服务节点设置为读写分离 Re…

计算机组成原理——第五章中央处理器(下)

梦里不知身是客&#xff0c;一晌贪欢 文章目录 5.6.1 指令流水线的基本概念5.6.2 指令流水线的影响因素和分类五段式指令流水线5.7.1 多处理器的基本概念5.7.2 硬件多线程的基本概念 5.6.1 指令流水线的基本概念 想要对指令的过程进行优化&#xff0c;一条指令的执行过程可以被…

世界新冠疫情数countrydata.csv 表,实战分析

一、环境要求 Hadoop hive spark hbase开发环境 开启hadoop&#xff1a;start-all.sh开启zookeeper&#xff1a;zkServer.sh start开启hive&#xff1a;nohup hive --service metastore &nohup hive --service hiveserver2 & 打开hive界面&#xff1a;beeline -u …

单列集合之Set集合以及各种实现类

Set集合 Set接口也是Collection单列结合的一个子接口&#xff0c;set集合中没有提供其他额外的方法&#xff0c;但是相比较Collection集合新增了其他的特性。所有实现了Set接口的类都可以叫做Set集合。 Coliection接口中的方法&#xff1a;Collection集合的方法 Set集合不允…

更全面的对比GPT4和Claude对MLIR的掌握能力

本文构造了20个MLIR基础概念的问题以及使用OneFlow IR转换为Tosa IR的5个代码段来评测GPT4和Claude对于MLIR的掌握能力&#xff0c;我的结论是对于基础概念的理解Claude整体上和GPT4持平&#xff0c;而在阅读相关代码片段时Claude表现出了比GPT4更强一点的理解能力。 0x0. 前言…

【Python】读取r语言数据+NMF算法(完整代码+详细注释)

目录 依赖库代码功能完整代码总结 欢迎关注 『Python』 系列&#xff0c;持续更新中 欢迎关注 『Python』 系列&#xff0c;持续更新中 算法部分源码是我的数模兄弟想要深入研究nmf算法方面的内容发给我让我跑的 参考自博文 https://blog.csdn.net/atease0001/article/details/…

计及光伏电站快速无功响应特性的分布式电源优化配置方法(Matlab代码实现)

&#x1f4a5; &#x1f4a5; &#x1f49e; &#x1f49e; 欢迎来到本博客 ❤️ ❤️ &#x1f4a5; &#x1f4a5; &#x1f3c6; 博主优势&#xff1a; &#x1f31e; &#x1f31e; &#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 …

JS的函数定义和参数

文章目录 一、JavaScript 函数定义二、JavaScript 函数参数总结 一、JavaScript 函数定义 JavaScript 使用关键字 function 定义函数。 函数可以通过声明定义&#xff0c;也可以是一个表达式。 函数声明 function functionName(parameters) {执行的代码 }函数声明后不会立即…

【C++内联函数】

目录 前言内联函数的概念内联函数的特性内联函数的总结 前言 假设有这样的一个场景&#xff0c;有一个代码量不足三行的函数被调用了一万次&#xff0c;现在让你做优化&#xff0c;你会怎么考虑优化&#xff1f; 我们都知道函数调用是有时间和空间开销的。程序在执行一个函数之…

Ansys Lumerical | 使用 STACK 仿真抗反射偏振器件

1、说明 在本示例中&#xff0c;我们将展示使用 Lumerical STACK 求解器来设计抗反射圆偏振器&#xff0c;以减少 OLED 显示器的环境光反射。 2、综述 OLED 显示器的底部金属电极可以用于增强光提取效率&#xff0c;然而它也会带来环境光反射的不利影响&#xff0c;导致显示器在…

深度学习-基础(二)-numpy中的轴操作

背景 使用Pytorch进行学习&#xff0c;少不了跟numpy打交道&#xff0c;比如数据集中去除通道reduction只有做加法运算等&#xff0c;但是numpy轴操作&#xff0c;很少有人讲清楚&#xff0c;此处加以梳理。 轴的概念 轴用来为超过一维的数组定义的属性&#xff0c;二维数据…

【Atlas500】华为500小站预配置

目录 基础配置解决配置能力项未开启问题 基础配置 1.网线连接盒子 2.1口IP:192.168.2.111 2口IP&#xff1a;192.168.3.111 3.登临网页https://192.168.2.111 输入用户名和密码&#xff08;管理端用户&#xff09;。 ● 默认用户名&#xff1a;admin ● 默认密码&#xff1a;H…

Eclipse安装插件及所有插件下载地址汇总

Eclipse安装插件及所有插件下载地址汇总 插件的意义安装插件各插件下载地址汇总kepler&#xff08;Eclipse配置本地安装好的Tomcat时使用的插件&#xff09;另一个插件名称 插件的意义 自认是为了解耦&#xff0c;使使用eclipse的人可以依据自己所需&#xff0c;有针对性的下载…

MySQL_第04章_运算符

第04章_运算符 讲师&#xff1a;尚硅谷 - 宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a; http://www.atguigu.com 1. 算术运算符 算术运算符主要用于数学运算&#xff0c;其可以连接运算符前后的两个数值或表达式&#xff0c;对数值或表达式…