MySQL-笔记-06.数据高级查询

目录

6.1 连接查询

6.1.1 交叉连接(cross join)

6.1.2 内连接(inner join)

6.1.3 外连接(outer join)

6.1.3.1 左外连接(left [outer] join)

6.1.3.2 右外连接(right [outer] join)

6.1.4 自连接(cross join)

6.2 嵌套查询

6.2.1 单值嵌套查询

6.2.2 多值嵌套查询

6.2.2.1 使用in运算符

6.2.2.2 使用比较运算符的子查询

6.2.2.3 使用any、all运算符

6.2.2.4 使用EXISTS连接的子查询

6.3 集合查询

6.3.1 union形成并集

6.3.2 except形成差集

小结:

6.1 连接查询

        数据库本着精简的设计原则,通常将数据存放于不同的表中,最大限度地减少数据冗余。在实际应用中,经常需要从多个数据表中查询满足一定条件的记录,这时就要用到连接查询。

连接查询分为交叉连接内连接外连接自连接

6.1.1 交叉连接(cross join)

        交叉连接返回被连接表中所有数据行的笛卡尔积

        查询结果集的总行数=被连接表行数的乘积总列数=被连接表列数的总和

        其基本语法格式如下:

SELECT * FROM 表名1 CROSS JOIN 表名2

        在from子句中也可以省略cross join,使用逗号分隔被连接的表,

        其基本语法格式如下:

SELECT * FROM 表名1 , 表名2

         交叉连接产生的结果集一般没有实际应用的意义,所以这种连接很少使用。

6.1.2 内连接(inner join)

        内连接是最常使用的连接查询方式,通过inner join或者join连接两个表,结果集中只包含满足连接条件的记录。连接条件通常采用“主键 = 外键”的形式。

        内连接创建连接关系有以下两种方式:

①在WHERE子句中创建连接关系,两个表名出现在FROM子句中,其基本语法格式如下:

SELECT 列名列表
FROM 表名1 , 表名2 WHERE 表名1.列名 = 表名2.列名

② 在FROM子句中创建连接关系,其基本语法格式如下:

SELECT 列名列表
FROM 表名1 [ INNER ] JOIN 表名2 ON 表名1.列名 = 表名2.列名

 【例3.102】查询所有选课学生的学号、所选课程的名称和成绩。

SELECT score.cno, cname, grade
FROM course, score
WHERE course.cno = score.cno;		/*在WHERE子句中给出等值连接查询条件*/

 【例3.103】查询男学生的选课情况。要求列出学号、姓名、性别、课程名、课程号和成绩。

-- 方法1
SELECT A.sno, A.sname, A. ssex, C.cname, C.cno, B.grade
FROM student A INNER JOIN score B ON A.sno = B. sno 	/*可省略INNER*/
     INNER JOIN course C ON B.cno = C.cno 
WHERE (A.ssex = '男') ; 


-- 方法2
SELECT A.sno, A.sname, A. ssex, C.cname, C.cno, B.grade
FROM student A, score B, course C
WHERE A.sno = B. sno AND B.cno = C.cno AND A.ssex = '男';

6.1.3 外连接(outer join)

        在内连接查询中,结果集只包括满足连接条件的数据行,但有时用户也希望在结果集中能显示那些不满足连接条件的数据,这就需要使用外连接查询

        外连接操作的类型可分为左外连接和右外连接。

        在创建外连接时,表在SQL语句中出现的顺序非常重要。

        出现在JOIN左边的表是“左表”,出现在JOIN右边的表是“右表”。

6.1.3.1 左外连接(left [outer] join)

        左外连接指定在结果集中除了包括由内连接返回的所有行之外,还包括左表中所有不满足连接条件的行,并将结果集中右表的输出列设置为NULL。

        因此,左外连接可以使得左表中的所有记录都显示在结果集中

        左外连接是对连接条件中左边表不加限制,其基本语法格式如下:

SELECT 列名列表 
FROM 表名1 LEFT [OUTER] JOIN 表名2 ON 表名1.列名 = 表名2.列名

 【例3.102】student表左外连接score表。

SELECT A.sno, A.sname, B.cno, B.grade 
FROM student A LEFT OUTER JOIN score B ON A.sno = B.sno;
6.1.3.2 右外连接(right [outer] join)

        右外连接指定结果集中除了包括由内连接返回的所有行之外,还包括右表中所有不满足连接条件的行,并将结果集中左表的输出列设置为NULL。

        因此,右外连接可以使得右表中的所有记录都显示在结果集中

        右外连接是对连接条件中右边表不加限制,其基本语法格式如下:

SELECT 列名列表 
FROM 表名1 RIGHT [OUTER] JOIN 表名2 ON 表名1.列名 = 表名2.列名

 【例3.107】teacher表右外连接lesson表。

SELECT A.tno, A.tname, B.*
FROM teacher A RIGHT OUTER JOIN lesson B ON A.tno = B.tno;

6.1.4 自连接(cross join)

        自连接是指一个表自己与自己建立连接,也称为自身连接

        若要在一个表中找具有相同列值的行,则可以使用自连接。

        使用自连接时需要为表指定两个别名,且对所有列的引用均要用别名限定

【例3.101】查询选修“数据库原理”(课程号01301)课程的成绩高于学号为202301020101的学生的成绩的所有学生信息,并按成绩从高到低排列。

SELECT x.* 
FROM score x , score y			/*将成绩表score分别取别名为x和y*/
WHERE x.cno= '01301' and x.grade > y. grade and 
	y.sno= '202301020101' and y.cno= '01301' 
ORDER BY x. grade DESC;

 多学一招:

        在连接查询时,若数据表连接的字段同名,则连接时的匹配条件可以使用using代替on

        基本语法格式如下:

SELECT 列名列表
FROM 表名1 [ inner | left | right ] join 表名2 
using(列名)

 【例3.103】查询男学生的选课情况。要求列出学号、姓名、性别、课程名、课程号和成绩。

SELECT A.sno, A.sname, A. ssex, C.cname, C.cno, B.grade
FROM student A JOIN score B USING(sno)
              INNER JOIN course C USING(cno) 
WHERE (A.ssex = '男') ; 

 注意:

        如果连接的表中有相同的列名,要求加上表名或表别名作为前缀来限定列名,即用“表名.列名”或“表别名.列名”表示,明确列名来自哪个数据表,否则系统将无法执行此查询,并提示错误信息。表别名往往是一个缩短了的表名,如果定义了表别名,则不能使用表名。如果列名不重名,可以不加表名或表别名前缀。

        连接查询,需要根据要解决的问题进行分析

  •         结果来自哪几个表(确定连接表)?
  •         表之间建立怎样的连接(确定连接类型)?
  •         选取怎样的数据(SELECT 字段名)?

只有将这些问题搞清楚,才可能写出正确的语句。

6.2 嵌套查询

        在SQL语言中,一个SELECT … FROM … WHERE语句称为一个查询块,将一个查询块嵌套在另一个查询块中的查询称为嵌套查询。

在嵌套查询中,上层查询块称为外层查询或父查询,下层查询块称为内层查询或子查询。        

SQL语言允许多层嵌套查询,即一个子查询中还可以嵌套其他子查询。

嵌套查询一般按照由里向外的顺序处理,即先处理最内层的子查询,然后一层一层向外处理,直到最外层查询块。

需要注意以下几点:

  • 子查询语句必须用圆括号括起来
  • 子查询中不能使用ORDER BY子句,ORDER BY子句只能对最终查询结果进行排序。
  • 有些嵌套查询可以用连接查询替代

6.2.1 单值嵌套查询

 单值嵌套查询是指子查询返回一个单一的值(即标量)。

【例3.109】查询选修“数据库原理”课程的所有学生的学号和成绩。

-- 方法1
SELECT sno, grade 
FROM score 
WHERE cno=( 
   SELECT cno 
   FROM course 
   WHERE cname='数据库原理');

-- 方法2
ELECT S.sno, S.grade 
FROM score S JOIN course C  USING(cno)
WHERE  cname='数据库原理';

6.2.2 多值嵌套查询

        多值嵌套查询是指子查询返回一个结果集,这个结果集包含多行数据

        这种子查询通常与any、all、in、not in、exits、not exits等操作符一起使用。

6.2.2.1 使用in运算符

        IN 是属于的意思,等价于“=ANY”,即等于子查询结果集中的任何一个值。

【例3.110】查询与“陈嘉宁”在同一个班级学习的学生。

-- 方法1
SELECT sno, sname, clsno
FROM student
WHERE clsno IN  -- in可以换成=
    (SELECT clsno 
     FROM student
     WHERE sname= '陈嘉宁')
-- 方法2
SELECT S1.sno, S1.sname, S1. clsno
FROM student S1 JOIN student S2 USING(clsno)
WHERE S2.sname = '陈嘉宁'

 【例3.111】查询选修了课程名为“数据结构”课程的学生的学号和姓名。

-- 方法1
SELECT sno, sname
FROM student
WHERE sno IN (
	SELECT sno
	FROM score
	WHERE cno IN (
		SELECT cno
		FROM course
		WHERE cname= '数据结构'
	)
)

-- 方法2
SELECT student.sno, sname
FROM student, score, course
WHERE student.sno = score.sno AND score.cno = course.cno AND course.cname= '数据结构' 
6.2.2.2 使用比较运算符的子查询

        带有比较运算符的子查询是指父查询与子查询之间用比较运算符进行连接。

        当用户确切知道内层查询返回单个值时,可以用>、<、=、>=、<=、!=或<>等比较运算符。

【例3.112】查询与“陈嘉宁”在同一个班级学习的学生。

SELECT sno, sname, clsno
FROM student
WHERE clsno =
    (SELECT clsno 
     FROM student
     WHERE sname= '陈嘉宁')

 【例3.113】找出每个学生超过他选修课程平均成绩的课程号。

SELECT cno
FROM score x
WHERE grade >= (
    SELECT AVG (grade) 
    FROM score y
    WHERE y.sno=x.sno)
6.2.2.3 使用any、all运算符

        子查询返回单值可以用比较运算符,但返回多值时要用ANY(SOME)或ALL谓词修饰符。

        而使用ANY或ALL谓词的时候必须同时使用比较运算符。 其基本语法格式如下:

expression {> | >= | = | < | <= | <> | != | <=> } { ALL | ANY | SOME } ( subquery )

      

 【例3.114】查询其他班级中比“2023计科1班”某一学生年龄小的学生的姓名和出生日期。

        1.首先找出“2023计科1班”中所有学生的年龄,构成一个集合

        2.找所有不是“2023计科1班”且年龄小于上述集合中任一值的学生

SELECT sname, sbirthday 
FROM student
WHERE sbirthday  < ANY ( SELECT sbirthday
                         FROM student
                         WHERE clsno  =( SELECT clsno                                                
                                         FROM class
                                         WHERE clsname= '2023计科1班')
                        ) 
                   AND clsno<> ( SELECT clsno
                                 FROM class
                                 WHERE clsname= '2023计科1班' 
                                ) 

 ANY和ALL谓词有时可以用集函数实现

ANY与ALL与集函数的对应关系

        用集函数实现子查询通常比直接用ANY或ALL查询效率要高

        因为前者通常能够减少比较次数

 练习: 找出比女生年龄都小的学生的学号、姓名和性别。

-- 方法1
select sno,sname, ssex
from student
where sbirthday > all (
	select sbirthday    
	from student  
	where ssex ='女' )

-- 方法2
select sno,sname, ssex
from student
where sbirthday > (
	select max(sbirthday)   
	from student  
	where ssex ='女' )
6.2.2.4 使用EXISTS连接的子查询

        EXISTS和NOT EXISTS关键字用来确定数据是否在子查询结果集中存在。

exists表示子查询至少返回一行时条件成立,

not exists表示子查询中没有任何记录返回时条件成立

        使用exists连接子查询时,相当于对外部查询的数据行进行了一次存在测试。

        外部查询的where子句测试满足子查询的行是否存在。

        带有exists的子查询不返回任何数据行,它只返回true或false。

【例3.118】查询教师工号为“01001”的教师讲授的课程的课程号、课程名和学时。

SELECT cno, cname, chour
FROM course
WHERE EXISTS (
   SELECT * FROM lesson WHERE cno=course.cno AND tno='01001');


SELECT cno, cname, chour
FROM course
WHERE cno IN (
   SELECT cno FROM lesson WHERE tno='01001');


SELECT cno, cname, chour
FROM course
WHERE '01001' IN (
   SELECT tno FROM lesson WHERE cno=course.cno);


SELECT DISTINCT course.cno, cname, chour
FROM course INNER JOIN lesson USING(cno) WHERE tno='01001';

 【例3.119】查询还没有学生选课的课程信息。

SELECT * FROM course A 
WHERE NOT EXISTS
(SELECT cno FROM score WHERE cno=A.cno);

【练习】 查询没有选修01101号课程的学生学号、姓名。

SELECT sno, sname
FROM student
WHERE NOT EXISTS(SELECT *
                 FROM score
                 WHERE score.sno = student.sno  AND cno='01101');

 【练习】查询选修全部课程的学生姓名。

-- 方法1
SELECT sname
FROM student
WHERE NOT EXISTS (SELECT *  FROM course
              	  WHERE NOT EXISTS (SELECT * FROM score
                   		            WHERE sno= student.sno
                      	            AND cno= course.cno
		                            )
                  );
-- 方法2
select sname
From student
Where sno IN(select sno
             from score
             Group by sno
             Having count(*) = (select count(*) from course)
             )

6.3 集合查询

        集合运算符将来自两个或多个查询的结果合并到单个结果集中。T-SQL支持三种集合运算:并集(UNION)、交集(INTERSECT)、差集(EXCEPT)。

集合运算的限定条件如下:

(1)子结果集要具有相同的结构。

(2)子结果集的列数必须相同。

(3)子结果集对应的数据类型必须可以兼容。

(4)每个子结果集不能包含ORDER BY和COMPUTE子句。

集合运算的语法如下:

select_statement
集合运算符
select_statement
[集合运算符] select_statement … ]

6.3.1 union形成并集

【例3.120】查询“2023计科1班”的学生或2005年以后出生的学生。

SELECT *
FROM student
WHERE clsno= '2023010101'
UNION
SELECT *
FROM student
WHERE YEAR (sbirthday) > 2005;

SELECT DISTINCT *
FROM student
WHERE clsno= '2023010101' OR YEAR (sbirthday) > 2005;

6.3.2 except形成差集

【例3.122】查询“2023计科1班”的学生与2005年以后出生的学生的差集。

SELECT *
FROM student
WHERE clsno= '2023010101'
EXCEPT
SELECT *
FROM student
WHERE YEAR (sbirthday) > 2005;

SELECT DISTINCT *
FROM student
WHERE clsno= '2023010101' AND YEAR (sbirthday) <= 2005;

小结:

实施查询任务,可按照以下步骤进行分析,并逐步实现。

步骤1:分析查询涉及的表,包括查询条件和查询结果涉及的表,确定是单表查询,还是多表查询,确定FROM子句中的表名。

步骤2:如果是多表查询,分析确定表与表之间的连接条件,即确定FROM子句中ON后面的连接条件

步骤3:分析查询是针对所有行,还是选择部分行。如果是选择部分行,使用WHERE子句,确定WHERE子句中的行条件表达式。

步骤4:分析查询是否要进行分组统计计算。如果需要分组统计,则使用GROUP BY子句,确定分组的列名。然后分析分组后是否要对组进行筛选,如果需要,则使用HAVING子句,确定组筛选条件。

步骤5:确定查询目标列表达式,即确定查询结果包含的列名或列表达式,确定SELECT子句后的目标列表达式。

步骤6:分析是否要对查询结果进行排序,如果需要排序,则使用ORDER BY子句,确定排序的列名和排序方式。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第2章:车辆纵向控制

2.1 车辆纵向动力学模型 注&#xff1a;车辆的纵向控制是指控制车辆行驶方向上的加减速&#xff0c;使得汽车可以按照期望的速度行驶&#xff0c;并保持安全的前后车距&#xff08;即对汽车油门 / 刹车的控制&#xff09;&#xff1b; 2.1.1 车辆纵向受力模型 &#xff1a;轮胎…

SpringBootSpringCloud升级可能会出现的问题

1.背景 之前负责过我们中台的SpringBoot和Cloud的升级&#xff0c;特次记录分享一下项目中可能出现的问题&#xff0c;方便后续的人快速定位问题。以及下述选择的解决方案都是基于让升级的服务影响和改动最小以及提供通用的解决方案的提前进行选择的。 1.1版本说明 升级前&a…

OpenCV基本图像处理操作(十)——图像特征harris角点

角点 角点是图像中的一个特征点&#xff0c;指的是两条边缘交叉的点&#xff0c;这样的点在图像中通常表示一个显著的几角。在计算机视觉和图像处理中&#xff0c;角点是重要的特征&#xff0c;因为它们通常是图像中信息丰富的区域&#xff0c;可以用于图像分析、对象识别、3D…

JavaSE中的String类

1.定义方式 常见的三种字符串构造 public class Test1 {public static void main(String[] args) {// 使用常量串构造String str1 "abc";System.out.println(str1);// 直接newString对象String str2 new String("ABC");System.out.println(str2);// 使用…

【Linux学习】Linux指令(四)

文章标题 &#x1f680;zip/unzip指令&#xff1a;&#x1f680;tar指令&#xff08;重要&#xff09;&#xff1a;&#x1f680;uname –r指令&#xff1a;&#x1f680;关机指令&#x1f680;几个常用操作 &#x1f680;zip/unzip指令&#xff1a; zip 与 unzip的安装 yum i…

Day20-【Java SE高级】单元测试 反射 注解 动态代理

一、单元测试 就是针对最小的功能单元(方法)&#xff0c;编写测试代码对其进行正确性测试。 1. 咱们之前是如何进行单元测试的?有啥问题? 只能在main方法编写测试代码&#xff0c;去调用其他方法进行测试。无法实现自动化测试&#xff0c;一个方法测试失败&#xff0c;可能…

学习在Debian系统上安装Shadowsocks教程

学习在Debian系统上安装Shadowsocks教程 安装shadowsocks-libev及其所需的依赖启动Shadowsocks服务&#xff1a;如果你想要通过代理本地流量&#xff0c;你可以使用ss-local&#xff1a;启动并设置ss-local&#xff1a;查看状态本地连接 安装shadowsocks-libev及其所需的依赖 …

量化交易为什么独宠Python

“我在学一门叫Python的语言”。“什么是Python&#xff0c;没听说过啊&#xff0c;为什么不学C啊”。这是发生在2014年&#xff0c;上海的一家量化基金&#xff0c;量化研究员和老板之间的对话。 “我想问一下关于Python的课程&#xff0c;什么时候能开班”。“Python啊&#…

数据结构-栈和队列刷题集(长期更新)

文章目录 万能计算器的实现以及源码分析1. leetcode 150 逆波兰表达式求值 万能计算器的实现以及源码分析 /*** 我们尝试写一个完整版的计算器,由于计算机不能很好的识别括号,所以一般要转换为逆波兰表达式求解* 思路解析 :* 1. 输入一个 中缀表达式* 2. 中缀表达式转化为list…

Python 数据结构和算法实用指南(一)

原文&#xff1a;zh.annas-archive.org/md5/66ae3d5970b9b38c5ad770b42fec806d 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 前言 数据结构和算法是信息技术和计算机科学工程学习中最重要的核心学科之一。本书旨在提供数据结构和算法的深入知识&#xff0c;以及编程…

28岁转行嵌入式适合转嵌入式吗?

转行到嵌入式领域是一个很好的选择&#xff0c;特别是如果你对电子技术、嵌入式系统和软硬件交互感兴趣的话。我这里有一套嵌入式入门教程&#xff0c;不仅包含了详细的视频 讲解&#xff0c;项目实战。如果你渴望学习嵌入式&#xff0c;不妨点个关注&#xff0c;给个评论222&a…

信息系统项目管理师0054:运维和服务(4信息系统管理—4.1管理方法—4.1.4运维和服务)

点击查看专栏目录 文章目录 4.1.4运维和服务1.运行管理和控制2.IT服务管理3.运行与监控4.终端侧管理5.程序库管理6.安全管理7.介质控制8.数据管理4.1.4运维和服务 信息系统的运维和服务应从信息系统运行的视角进行整合性的统筹规划,包括对信息系统、应用程序和基础设施的日常控…

C语言的OJ判题机设计与实现

1. 接收判题入参 判题需要作答代码、测试输入和期望输出、编译器名称、时空限制。对于支持special judge的还需要传入是否为sj和sj代码。推荐使用消息队列&#xff0c;应对高并发的比赛情况会比较好。 但是消息队列是异步的&#xff0c;我为了快点实现能提交后在当前页面获得判…

Elasticsearch:(一)ES简介

搜索引擎是什么&#xff1f;在不少开发者眼中&#xff0c;ES似乎就是搜索引擎的代名词&#xff0c;然而这实际上是一种误解。搜索引擎是一种专门用于从互联网中检索信息的技术工具&#xff0c;它主要可以划分为元搜索引擎、全文搜索引擎和垂直搜索引擎几大类。其中&#xff0c;…

AIGC算法1:Layer normalization

1. Layer Normalization μ E ( X ) ← 1 H ∑ i 1 n x i σ ← Var ⁡ ( x ) 1 H ∑ i 1 H ( x i − μ ) 2 ϵ y x − E ( x ) Var ⁡ ( X ) ϵ ⋅ γ β \begin{gathered}\muE(X) \leftarrow \frac{1}{H} \sum_{i1}^n x_i \\ \sigma \leftarrow \operatorname{Var}(…

【中级软件设计师】上午题08-UML(下):序列图、通信图、状态图、活动图、构件图、部署图

上午题08-UML 1 序列图2 通信图3 状态图3.1 状态和活动3.2 转换和事件 4 活动图5 构件图&#xff08;组件图&#xff09;6 部署图 【中级软件设计师】上午题08-UML(上)&#xff1a;类图、对象图、用例图 UML图总和 静态建模&#xff1a;类图、对象图、用例图 动态建模&#xff…

【简单介绍下PostCSS】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

仿真测试的应用领域

仿真测试在各种领域中都有广泛的应用&#xff0c;以下是一些应用最广泛的场景&#xff1a; 工业制造&#xff1a;通过模拟制造过程&#xff0c;可以预测产品的质量和性能&#xff0c;优化生产流程&#xff0c;降低成本。航空航天&#xff1a;飞机、导弹、航天器等的设计和研发…

AWS Key disabler:AWS IAM用户访问密钥安全保护工具

关于AWS Key disabler AWS Key disabler是一款功能强大的AWS IAM用户访问密钥安全保护工具&#xff0c;该工具可以通过设置一个时间定量来禁用AWS IAM用户访问密钥&#xff0c;以此来降低旧访问密钥所带来的安全风险。 工具运行流程 AWS Key disabler本质上是一个Lambda函数&…

如何访问内网?

在互联网万维网上&#xff0c;我们可以轻松访问各种网站和资源。但是&#xff0c;有时我们需要访问局域网内的资源&#xff0c;例如公司内部的文件共享、打印机等。本文将介绍几种方法&#xff0c;帮助您实现访问内网的需求。 内网穿透技术 内网穿透技术是一种通过互联网将局域…