MySQL数据库10——多表连接查询

news2024/11/15 9:13:25

数据如果在多个表里面,需要进行连接查询。

一般在pandas里面merge合并会用到一个索引,按这个索引的规则进行合并叫做有规则的等值连接。若不按规则连接,遍历两两组合的所有可能性,叫做笛卡尔积。


笛卡尔积连接

通常人们都会设置连接规则,但无条件连接所得到的笛卡尔积有时也非常有用。例如下面的例子。

使用student表和course表的笛卡尔积,生成一个必修课成绩表(bxk_score)的内容,要求是每个学生都应该选择所有的必修课。

CREATE TABLE bxk_score AS
SELECT student.ID as 学号, student.name AS 姓名, course.ID AS 课号, course.course AS 课名
FROM student, course WHERE course.type='必修'
ORDER BY 学号, 课号;

运行上面的查询语句后,会生成bxk_Score表,对其执行查询语句如下。

SELECT * FROM bxk_score;

 本例使用笛卡尔积,自动生成了bxk_Score表的大部分内容。当然,该表还应该有一个“成绩”字段。该字段的添加可以在后期通过修改表结构的方法解决。

(1)创建一个临时表bbb,该表只有一个数值字段“成绩”。创建表的SQL语句如下所示。

(2)向bbb表插入记录,插入语句如下所示。

(3)修改SELECT语句如下所示。

CREATE TABLE bbb(score int);
INSERT INTO bbb(score) VALUES (0);
CREATE TABLE bxk_score AS
SELECT student.ID as 学号, student.name AS 姓名, course.ID AS 课号, course.course AS 课名,bbb.score
FROM student, course ,bbb WHERE course.type='必修'
ORDER BY 学号,课号;

 


使用两表连接查询数据

数据库操作中,比起使用笛卡尔积,使用有连接规则的连接查询会更频繁一些。下面通过一个例子介绍两表连接查询的具体使用方法。

查询名叫“张三”的学生的所有课程的平时成绩和考试成绩。

分析:student表中有学生姓名,但没有成绩,而存储成绩的score表中有成绩,但没有姓名,不过这两个表都有一个共同字段——学号,所以可以将这两个表连接起来进行查询,

SELECT student.ID AS 学号, student.name AS 姓名, score.c_id AS 课号,score.result2 AS 平时成绩, score.result1 AS 考试成绩
FROM student, score WHERE student.name = '张三' AND student.ID=score.s_id
ORDER BY score.result1 DESC,score.result2 DESC;

 


多表连接查询

继续上一节的话题,因为用户更希望看到课名,而不是课号,所以必须将存有课名的Course表也连接到Student和Score表上。

查询名叫“张三”的学生的所有课程的平时成绩和考试成绩。

分析:在上一节中,已经知道了Student和Score表可以用共同拥有的学号字段进行连接。接下来的问题是将Course表连接到上述两个表上。由于Student表和Course表没有共同字段所以不能连接,但是Score表和Course表有共同字段——课号,因此Score表和Course表可以连接,如此以来,经过Score表的搭桥,上述三个表就可以连接了,请参考下图所示。

SELECT  student.ID AS 学号, student.name AS 姓名, course.course AS 课名, score.result2 AS 平时成绩, score.result1 AS 考试成绩
FROM    student, score, course
WHERE   student.name = '张三' AND student.ID=score.s_id AND score.c_id=course.id
ORDER BY score.result1 DESC,score.result2 DESC;

 

 成功把课程代码换成课程名称了。


使用表别名简化语句

在前面曾经介绍过给字段起别名的方法,其实给表起别名与其非常类似。在FROM子句中,在表名的后面加上关键字“AS”和别名即可。例如,下面的查询语句使用表别名简化了上一小节例的查询语句。

SELECT a.ID AS 学号, a.name AS 姓名, c.course AS 课名, b.result2 AS 平时成绩, b.result1 AS 考试成绩 
FROM student AS a,score AS b,course AS c
WHERE a.name = '张三' AND a.ID=b.s_id AND b.c_id=c.ID
ORDER BY b.result1 DESC,b.result2 DESC;

例 查询“计算机基础” 课程,考试成绩大于等于90分的学生的学号、姓名、系别和考试成绩,并按考试成绩降序排序。

分析:课程名称在course表中,成绩在score表中,而姓名、系别在student表中,因此想要得到本例要求的结果,则必须对course、score和student三个表进行连接查询。

SELECT st.ID AS 学号, st.name AS 姓名, st.institute AS 所属院系, s.result1 AS 考试成绩
FROM score AS s,course AS c,student AS st
WHERE c.course='计算机基础' AND s.result1>=90 AND s.c_id=c.ID AND st.ID= s.s_id
ORDER BY s.result1 DESC;

 


使用INNER JOIN连接查询

因此在ANSI SQL规范中建议使用INNER JOIN进行多表连接。如此以来,WHERE子句中就不用再放置连接规则,而只放置查询条件就可以了。使用INNER JOIN连接n个表的语法格式如下所示。

SELECT  *(或字段列表) FROM   表名1
INNER JOIN 表名2
ON  接规则
INNER JOIN 表名3
ON  连接规则
……
INNER JOIN 表名n
ON  连接规则

其中,关键字“ON”之后是连接表的规则。

下面通过一个具体例题介绍INNER JOIN的用法。

例 查询所有考过“心理学” 课程的学生的学号、姓名、系别、“心理学”的平时成绩和考试成绩。

SELECT st.ID AS 学号, st.name AS 姓名, st.institute AS 所属院系, s.result2 AS 平时成绩, s.result1 AS 考试成绩
FROM score AS s
INNER JOIN course AS c   ON s.c_id=c.ID
INNER JOIN student AS st ON st.ID= s.s_id
WHERE c.course='心理学' ORDER BY s.result1 DESC;

 对应的WHERE语句:运行结果和上面相同。

SELECT  st.ID AS 学号, st.name AS 姓名, st.institute AS 所属院系, s.result2 AS 平时成绩, s.result1 AS 考试成绩
FROM   score AS s, course AS c, student AS st
WHERE  c.course='心理学' AND s.c_id=c.ID AND st.ID=s.s_id
ORDER BY s.result1 DESC;

 


 高级连接查询

自连接查询存

首先通过一个例题说明自连接查询存在的价值,其次介绍自连接查询的使用方法。

从student表中,查询“张三”所在院系的所有学生的信息。

分析:按照以前所学的知识,完成本例的查询任务需要两次查询,首先查询“张三”所在的院系是哪个院系,其次才能查询属于该院系的所有学生的信息。

(1)查询“张三”所在的院系名称。

SELECT  institute AS 所属院系
FROM   student
WHERE  name='张三‘

(2)根据上面查询,知道“张三”在中文系学习,下面查询“中文系”所有学生信息。

SELECT  * FROM   student
WHERE institute='中文系‘

上面两条语句可以一句话自连接查询完成,因为自连接查询可以用一条SELECT语句完成本例的查询任务。具体查询语句如下所示。

SELECT st1.* FROM student AS st1, student AS st2
WHERE st1.institute= st2.institute
AND st2.name='张三';

 为了强调连接规则的设置,下面再看一个例题。

例 从student表中查询与“吴刚”来源地相同的所有学生学号、姓名和所属院系。

SELECT st1.ID AS 学号, st1.name AS 姓名, st1.institute AS 所属院系
FROM student AS st1, student AS st2
WHERE st2.name='吴刚'
AND st1.origin=st2.origin;

 


内连接查询存

有规则的连接都属于内连接。内连接包括等值连接、自然连接、和不等值连接。

一、等值连接

前面几节的内容中,连接规则由等于号(=)组合而成,例如,st1.institute= st2.institute,并且列出两个表中所有字段的连接,即SELECT子句中使用星号(*)通配符的连接就属于等值连接。关于等值连接,由于前面的例子已经足够,因此不再具体举例说明。

二、自然连接

在等值连接的基础上稍加改动即可得到自然连接,等值连接将两个表中的所有字段全部列出,而自然连接则不将相同的字段显示两次,即在SELECT子句中列出需要显示的字段列表。

三、不等值连接

不等值连接的连接规则由等于号以外的运算符组成,例如,由>、>=、<、<=、<>或BETWEEN等。下面通过一个例题介绍不等值连接的使用方法。首先创建一个将要使用的年代对照表(nddzb),其创建语句和插入记录的语句分别如下所示。

例 从student表中,查询所有学生的出生年代。

分析:要完成此查询任务,需要将student表和nddzb连接起来,但是这两个表没有共同字段,所以没办法使用等值连接,而根据题意可以使用不等值连接。连接规则是如果student表的出生日期在nddzb的起始年份和终止年份之间就可以连接。

SELECT st.name AS 姓名,st.birthday AS 出生日期, n.年代
FROM student AS st,nddzb AS n
WHERE st.birthday BETWEEN n.起始年份 AND n.终止年份;

 


外连接查询存

在多表连接查询时,有时希望表的所有记录都被包含进去,即使没能匹配的记录也被查询结果集包含在内。这时,内连接查询已经满足不了需求了,所以应该采用另外一种连接查询方法——外连接查询,例如下图所示。外连接有左外连接、右外连接和全外连接三种。

 左外连接

这种连接的规则是将左外连接符号(LEFT OUTER JOIN或LEFT JOIN)左边的表的所有记录都包含到结果集中,而只将右边表中有匹配的记录包含进结果集,例如,如图10.22所示。实现图中左外连接的查询语句如下所示。

 对应代码

SELECT  * FROM   t1
LEFT OUTER  JOIN t2
ON  t1.职工号=t2.职工号

通过上图还可以知道,左外连接时,会将左边表的所有记录都会包含到查询结果中,这时,那些没有匹配的左边表的记录会与全部是NULL值的记录连接。

 右外连接

这种连接的规则是将右外连接符号(RIGHT OUTER JOIN或RIGHT JOIN)右边的表的所有记录都包含到结果集中,而只将左边表中有匹配的记录才包含进结果集,例如,如图10.23所示。实现图中右外连接的查询语句如下所示。

SELECT  * FROM   t1
RIGHT OUTER JOIN t2
ON  t1.职工号=t2.职工号

全外连接

这种连接的规则是将两个表的所有记录都包含到结果集中,而且,这种连接只有一种FULL OUTER JOIN连接符。例如下图

 在MySQL中不支持全外连接,要实现全外连接的效果,可以采用关键字UNION来联合左、右连接,具体查询语句如下:

SELECT  * FROM    t1
        LEFT JOIN t2
        ON  t1.职工号=t2.职工号

UNION
SELECT  * FROM   t1
        RIGHT JOIN t2
        ON  t1.职工号=t2.职工号

 


交叉连接查询

交叉连接类似笛卡尔积,无规则连接,例如将学生表和课程表连在一起。会生成120条数据。12(学生数量)*10(课程数量)

下面两种方法是相同的结果。

SELECT * FROM student,course;
SELECT * FROM student CROSS JOIN course;

 

连接查询中使用聚合函数

统计没有考过任何考试的学生人数

SELECT  COUNT(*) AS 没有考任何考试的人数 FROM    student AS st
LEFT OUTER JOIN score AS s ON st.ID=s.s_id
WHERE   s.s_id IS NULL;

 


 组合查询

有时,需要将多个查询语句的结果放到一起,以一个查询结果集的形式将其显示出来。这时就可以使用组合查询,组合查询是使用UNION关键字将多个SELECT查询语句组合起来查询的一种查询方法,其语法格式如下例子所示。

例 从student表中,查询来源地为“北京市”或者所属院系为“计科系”或者年龄大于25岁的学生的信息。运行环境为MySQL。

SELECT * FROM student WHERE origin='北京市'
UNION SELECT * FROM student WHERE institute='计科系'
UNION SELECT * FROM student WHERE TIMESTAMPDIFF(YEAR, birthday, CURDATE())>25;

例 从student表中,查询来源地为“北京市”或 “江苏省”或“内蒙古自治区”的学生的所属院系信息。

(1)下面的语句使用UNION完成查询任务。

SELECT institute AS 所属院系 FROM student WHERE origin='北京市'
UNION SELECT institute AS 所属院系 FROM student WHERE origin='江苏省'
UNION SELECT institute AS 所属院系 FROM student WHERE origin='内蒙古自治区';

 

 

(2)下面的语句使用OR完成查询任务。

SELECT institute AS 所属院系 FROM student
WHERE origin='北京市' OR origin='江苏省' OR origin='内蒙古自治区';

 使用UNION时,如果希望不删除重复值,则可以在UNION后加上ALL关键字。

使用UNION的规则

1、每个查询语句应当有相同数量的字段。

在使用UNION组合查询语句时,一定要注意每个单独的SELECT子句内的字段个数一定要相同。如果不同则会出现错误

2、每个查询语句中相应的字段的类型必须相互兼容

在每个查询语句字段个数相等的前提下,相应的字段的类型应当互相兼容。

技巧:当独立查询语句的字段个数不同时,可以在字段个数不够的地方使用常量补位。例如,在上面的第一个SELECT子句中补上一个NULL值,就可以避免错误,具体语句如下所示。

SELECT  ID, name, null
FROM    student
WHERE   origin='北京市'
UNION
SELECT  ID, name, birthday
FROM    student
WHERE   institute='计科系'

 使用UNION解决不支持全外连接的问题。

如上面的左连接和右连接合并就是全连接了。

使用UNION得到复杂的统计汇总样式

联合UNION、GROUP BY和聚合函数三者会得到具有很棒的统计汇总样式的查询结果,这也是OR所不能替代的。例如,下面的语句会得到一个具有复杂统计汇总样式的查询结果集。

SELECT s_id AS 学号, c_id AS 课号, result1 AS 考试成绩 FROM score
UNION SELECT s_id AS 学号, '总分:', SUM(result1) FROM score GROUP BY s_id
UNION SELECT s_id, '平均分:', AVG(result1) FROM score
GROUP BY s_id ORDER BY 学号, 课号;

 


 排序组合查询的结果

虽然组合查询中可以有多个单独的SELECT语句,而且每个独立的SELECT语句又都可以拥有自己的WHERE子句、GROUP BY子句和HAVING子句,但是,整个语句中却只能出现一个ORDER BY子句,而且它的位置必须在整个语句的末尾,就是说只能对组合查询最后的结果进行排序,而并不能只对某个单独的SELECT语句的结果进行排序。

SELECT st.name AS 姓名,c.ID AS 课号, c.course AS 课名, s.result1 AS 考试成绩
FROM  score AS s, student AS st,  course AS c
WHERE  s.s_id=st.ID AND s.c_id=c.ID
UNION
SELECT st.name AS 姓名,'999', '总分:',SUM(s.result1) AS 考试成绩
FROM  score AS s, student AS st
WHERE  s.s_id=st.ID
GROUP BY s.s_id,st.name
UNION
SELECT st.name AS 姓名, '999', '平均分:', AVG(s.result1) AS 考试成绩
FROM  score AS s, student AS st
WHERE  s.s_id=st.ID
GROUP BY s.s_id,st.name
ORDER BY 姓名, 课号

 

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

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

相关文章

R语言学习笔记

1.R语言介绍 2.R语言安装 官网&#xff1a;https://www.r-project.org/ CARN → 选择China中任意镜像站点 → Download R for Windows → base&#xff08;二进制版本R基础软件&#xff09;→ Download R-4.2.2 for Windows (76 megabytes, 64 bit) 3.Rstudio安装 https://po…

【Call for papers】SIGCOMM-2023(CCF-A/计算机网络/2023年2月15日截稿)

ACM SIGCOMM is the flagship annual conference of the ACM Special Interest Group on Data Communication (SIGCOMM). ACM SIGCOMM 2023, the 37th edition of the conference series, will be held in New York City, US, September 10 - 14, 2023. 文章目录1.会议信息2.时…

C语言(文件输入输出操作)

目录 一.文件 1.文件概念 2.文本模式和二进制模式 (1)模式结尾映射 (2)存储精度 3.I/O级别 一.文件 1.文件概念 文件:在磁盘或固态硬盘上一段已命名的存储区。对于C来说&#xff0c;文件就是一系列连续的字节&#xff0c;每个字节都能被单独读取&#xff08;在计算机当…

【C00033】基于Springboot的图书管理系统——有文档

基于Springboot的图书管理系统——有文档项目简介项目获取开发环境项目技术运行截图运行视频项目简介 基于springboot技术的图书管理系统主要是想研究一款高效且智能的图书管理系统&#xff0c;可以方便管理员以及借阅人员通过本系统更加快捷的完成图书借阅、查找等一系列操作…

ChatGPT不是聊天机器人,是任何人值得重视的竞争对手。

ChatGPT使用了一种聊天界面来和用户互动&#xff0c;用户的理解成本降低&#xff0c;通过输入文字&#xff0c;来得到各种反馈。有预见性的创造者们&#xff0c;已经挖掘ChatGPT所展示出来的各种能力应该如何更好地融入我们的日常生活中。比如&#xff0c;生成菜谱、音乐播放列…

1496奇怪的电梯(队列 广度优先搜索)

目录 题目描述 解题思路 代码部分 题目描述 大楼的每一层楼都可以停电梯&#xff0c;而且第i层楼&#xff08;1≤i≤N&#xff09;上有一个数字Ki(0≤Ki≤N&#xff09;。电梯只有四个按钮&#xff1a;开&#xff0c;关&#xff0c;上&#xff0c;下。上下的层数等于当前楼层…

套接字编程(四)TCP通信(万字详论)

TCP协议&#xff1a;面向连接的、可靠稳定的、基于字节流传输的通信协议 面向连接&#xff1a;通信之前首先要建立连接&#xff0c;确保双方具有收发数据的能力 可靠稳定的&#xff1a;通过大量的控制机制&#xff0c;保证数据能够安全有序且完整的到达对端 基于字节流&#xf…

【Vue3源码】第一章 effect和reactive

文章目录【Vue3源码】第一章 effect和reactive前言1、实现effect函数2、封装track函数&#xff08;依赖收集&#xff09;3、封装reactive函数4、封装trigger函数&#xff08;依赖触发&#xff09;5、单元测试【Vue3源码】第一章 effect和reactive 前言 今天就正式开始Vue3源码…

驱动 | Linux | NVMe 不完全总结

本文主要参考这里 1’ 2 的解析和 linux 源码 3。 此处推荐一个可以便捷查看 linux 源码的网站 bootlin 4。 更新&#xff1a;2022 / 02 / 11 驱动 | Linux | NVMe 不完全总结NVMe 的前世今生从系统角度看 NVMe 驱动NVMe CommandPCI 总线从架构角度看 NVMe 驱动NVMe 驱动的文件…

vue+nodejs考研资料分享系统vscode - Visual Studio Code

前端技术&#xff1a;nodejsvueelementui,视图层其实质就是vue页面&#xff0c;通过编写vue页面从而展示在浏览器中&#xff0c;编写完成的vue页面要能够和控制器类进行交互&#xff0c;从而使得用户在点击网页进行操作时能够正常。 Express 框架于Node运行环境的Web框架, 目 …

计算机网络5:数据在两台计算机之间是怎样传输的?

数据在两台计算机之间的传输总的来说包括了封装和解封两个过程 封装&#xff08;5层协议&#xff09; 以传送一张图片为例 **应用层&#xff1a;**将jpg格式的图片数据转化成计算机可以识别的0101的二进制的比特流 **传输层&#xff1a;**将应用层传输下来的数据进行分段&…

pandas数据分析35——多个数据框实现笛卡尔积

什么是笛卡尔积。就是遍历所有组合的可能性。 比如第一个盒子有[1,2,3]三个号码球&#xff0c;第二个盒子有[4,5]两个号码球。那么从每个盒子里面分别拿一个球共有3*2两种可能性&#xff0c;其集合就是{[1,4],[2,4],[3,4],[1,5],[2,5],[3,5]},这个就是笛卡尔积。 三个盒子也是…

GhostNet v2(NeurIPS 2022 Spotlight)原理与代码解析

paper&#xff1a;GhostNetV2: Enhance Cheap Operation with Long-Range Attentioncode&#xff1a;https://github.com/huawei-noah/Efficient-AI-Backbones/tree/master/ghostnetv2_pytorch背景在智能手机和可穿戴设备上部署神经网络时&#xff0c;不仅要考虑模型的性能&…

批量分析快递单号派件时效技巧

规定&#xff0c;如果出现派件延误商家没有及时处理&#xff0c;那么平台会对商家进行采取措施等等&#xff0c;同时商家每天都去跟踪自己发出单号物流状况&#xff0c;一个一个去查呢&#xff0c;不大可能&#xff0c;他们量是比较大&#xff0c;一个一个手动去官方查询工作量…

从元宇宙被认识的第一天开始,就注定了逃不脱区块链所经历的命运

从元宇宙被人们认识的第一天开始&#xff0c;它就注定了依然逃不脱它的先辈——区块链所经历的命运。如果对这样一种宿命进行一个总结的话&#xff0c;我更加愿意将其归结为以资本为主导的野蛮生长的发展模式。这种发展模式并不仅仅只是在区块链和元宇宙的身上出现&#xff0c;…

2016-ICLR-Order Matters- Sequence to sequence for sets

2016-ICLR-Order Matters- Sequence to sequence for sets Paper: [https://arxiv.org/pdf/1511.06391.pdf](https://arxiv.org/pdf/1511.06391.pdf) Code: 顺序重要性&#xff1a;集合的顺序到序列 摘要 许多需要从观察序列映射或映射到观察序列的复杂任务现在可以使用序列…

C++类基础(十一)

运算符重载&#xff08;二&#xff09; ● 对称运算符通常定义为非成员函数以支持首个操作数的类型转换 struct Str {int val 0;Str(int input): val(input){}auto operator(Str x){std::cout << "auto operator(Str x)\n";return Str(val x.val);} }; int …

git 常用命令之 git log

大家好&#xff0c;我是 17。 git log dev 查看 dev 分支的 log git log -p 每次提交所引入的差异 git log --stat 每次提交的简略统计信息 git log --name-status 比 --stat 更简洁&#xff0c;更常用。git log -2 最近两次提交 git log --since2.weeks 最近两周内的提交 git…

Linux通配符、转义符讲解

目录 通配符 通过通配符定义匹配条件 转义符 将所有的逻辑操作符都转换成字符 通配符 通过通配符定义匹配条件 * 任意字符都可以通配&#xff08;也可以匹配空值&#xff09; &#xff1f; 匹配单个字符 [a-z] 匹配单个的小写英文字母 [A-Z] 匹配单个的大写英文…

jQuery 基础知识(五)

前面已经介绍HTML、CSS和javaScript&#xff0c;这三个前端语言&#xff0c;俗称前端三剑客。下面来学习一个javaScript简化并封装好的库——jQuery库。01 - AJAX AJAX 是一种在无需重新加载整个网页的情况下&#xff0c;能够更新部分网页的技术。 AJAX的介绍 ajax 是 Asynchr…